forked from mindspore-Ecosystem/mindspore
!2100 add op quant and dequant
Merge pull request !2100 from zhaozhenlong/op/quant-dequant-ge-open
This commit is contained in:
commit
842f8231ba
|
@ -205,6 +205,8 @@ const char kNameL2Loss[] = "L2Loss";
|
|||
const char kNameCTCLoss[] = "CTCLoss";
|
||||
const char kNameRange[] = "Range";
|
||||
const char kNameSquareSumAll[] = "SquareSumAll";
|
||||
const char kNameAscendQuant[] = "AscendQuant";
|
||||
const char kNameAscendDequant[] = "AscendDequant";
|
||||
|
||||
// -----------------OpAdapter initialization--------------
|
||||
std::unordered_map<std::string, OpAdapterDescPtr> &DfGraphConvertor::get_adpt_map() {
|
||||
|
@ -408,7 +410,9 @@ std::unordered_map<std::string, OpAdapterDescPtr> &DfGraphConvertor::get_adpt_ma
|
|||
{string(kNameL2Loss), ADPT_DESC(L2Loss)},
|
||||
{string(kNameCTCLoss), ADPT_DESC(CTCLoss)},
|
||||
{string(kNameRange), ADPT_DESC(RangeD)},
|
||||
{string(kNameSquareSumAll), ADPT_DESC(SquareSumAll)}};
|
||||
{string(kNameSquareSumAll), ADPT_DESC(SquareSumAll)},
|
||||
{string(kNameAscendQuant), ADPT_DESC(AscendQuant)},
|
||||
{string(kNameAscendDequant), ADPT_DESC(AscendDequant)}};
|
||||
#ifdef ENABLE_GE
|
||||
adpt_map[string(kNamePrint)] = ADPT_DESC(Print);
|
||||
adpt_map[string(kNameApplyAdam)] = ADPT_DESC(ApplyAdamD);
|
||||
|
|
|
@ -1277,6 +1277,19 @@ ATTR_MAP(CTCLoss) = {
|
|||
{"ignore_longer_outputs_than_inputs", ATTR_DESC(ignore_longer_outputs_than_inputs, AnyTraits<bool>())}};
|
||||
OUTPUT_MAP(CTCLoss) = {{0, OUTPUT_DESC(loss)}, {1, OUTPUT_DESC(gradient)}};
|
||||
|
||||
// AscendQuant
|
||||
INPUT_MAP(AscendQuant) = {{1, INPUT_DESC(x)}};
|
||||
ATTR_MAP(AscendQuant) = {{"scale", ATTR_DESC(scale, AnyTraits<float>())},
|
||||
{"offset", ATTR_DESC(offset, AnyTraits<float>())},
|
||||
{"sqrt_mode", ATTR_DESC(sqrt_mode, AnyTraits<bool>())},
|
||||
{"round_mode", ATTR_DESC(round_mode, AnyTraits<std::string>())}};
|
||||
OUTPUT_MAP(AscendQuant) = {{0, OUTPUT_DESC(y)}};
|
||||
|
||||
// AscendDequant
|
||||
INPUT_MAP(AscendDequant) = {{1, INPUT_DESC(x)}, {2, INPUT_DESC(deq_scale)}};
|
||||
ATTR_MAP(AscendDequant) = {{"sqrt_mode", ATTR_DESC(sqrt_mode, AnyTraits<bool>())},
|
||||
{"relu_flag", ATTR_DESC(relu_flag, AnyTraits<bool>())}};
|
||||
OUTPUT_MAP(AscendDequant) = {{0, OUTPUT_DESC(y)}};
|
||||
#ifdef ENABLE_GE
|
||||
// Print
|
||||
INPUT_MAP(Print) = EMPTY_INPUT_MAP;
|
||||
|
|
|
@ -481,6 +481,10 @@ DECLARE_OP_ADAPTER(L2Loss)
|
|||
DECLARE_OP_USE_OUTPUT(L2Loss)
|
||||
DECLARE_OP_ADAPTER(CTCLoss)
|
||||
DECLARE_OP_USE_OUTPUT(CTCLoss)
|
||||
DECLARE_OP_ADAPTER(AscendQuant)
|
||||
DECLARE_OP_USE_OUTPUT(AscendQuant)
|
||||
DECLARE_OP_ADAPTER(AscendDequant)
|
||||
DECLARE_OP_USE_OUTPUT(AscendDequant)
|
||||
#ifdef ENABLE_GE
|
||||
DECLARE_OP_ADAPTER(Print)
|
||||
DECLARE_OP_USE_DYN_INPUT(Print)
|
||||
|
|
|
@ -39,6 +39,8 @@ __all__ = ["FakeQuantPerLayer",
|
|||
"BatchNormFold2_D",
|
||||
"BatchNormFold2GradD",
|
||||
"BatchNormFold2GradReduce",
|
||||
"AscendQuant",
|
||||
"AscendDequant",
|
||||
]
|
||||
|
||||
|
||||
|
@ -975,3 +977,104 @@ class FakeQuantMinMaxPerChannelUpdate(PrimitiveWithInfer):
|
|||
validator.check_tensor_type_same(
|
||||
{"max": max_type}, valid_types, self.name)
|
||||
return min_type, max_type
|
||||
|
||||
|
||||
class AscendQuant(PrimitiveWithInfer):
|
||||
r"""
|
||||
Returns the quantized value of input_x.
|
||||
|
||||
If `sqrt_mode` is False:
|
||||
|
||||
.. math::
|
||||
y = round(scale * x + offset)
|
||||
If `sqrt_mode` is True:
|
||||
|
||||
.. math::
|
||||
y = round(scale * x * scale + offset)
|
||||
|
||||
Note:
|
||||
This operation only support Ascend 310 inference environment.
|
||||
|
||||
Args:
|
||||
scale (float) : Specifies the scaling ratio.
|
||||
offset (float): Specifies the offset.
|
||||
sqrt_mode (bool) : Specifies whether to perform square root on `scale`. Default: False.
|
||||
round_mode (str): Specifies the way to round. Should be one of ["Round", "Floor", "Ceil", "Trunc"].
|
||||
Default: "Round".
|
||||
|
||||
Inputs:
|
||||
- **input_x** (Tensor) : Input tensor. Its data type should be mindspore.float16 or mindspore.float32.
|
||||
|
||||
Outputs:
|
||||
- Tensor: The quantized output tensor of type mindspore.int8.
|
||||
|
||||
Examples:
|
||||
>>> input_x = Tensor([100.0, 150.0], mstype.float32)
|
||||
>>> quant = P.AscendQuant(80.0, 0.0, False, "Round")
|
||||
>>> y = quant(input_x)
|
||||
"""
|
||||
|
||||
@prim_attr_register
|
||||
def __init__(self, scale, offset, sqrt_mode=False, round_mode="Round"):
|
||||
self.scale = validator.check_value_type("scale", scale, [float], self.name)
|
||||
self.offset = validator.check_value_type("offset", offset, [float], self.name)
|
||||
self.sqrt_mode = validator.check_value_type("sqrt_mode", sqrt_mode, [bool], self.name)
|
||||
self.round_mode = validator.check_string("round_mode", round_mode,
|
||||
["Round", "Floor", "Ceil", "Trunc"], self.name)
|
||||
|
||||
def infer_shape(self, x_shape):
|
||||
return x_shape
|
||||
|
||||
def infer_dtype(self, x_type):
|
||||
validator.check_subclass("input_x", x_type, mstype.tensor, self.name)
|
||||
validator.check_type_name("input_x", x_type, [mstype.float16, mstype.float32], self.name)
|
||||
return mstype.int8
|
||||
|
||||
|
||||
class AscendDequant(PrimitiveWithInfer):
|
||||
r"""
|
||||
Returns the dequantized value of input_x.
|
||||
This operation will do ReLU to the dequantized value if `relu_flag` is True.
|
||||
|
||||
If `sqrt_mode` is False:
|
||||
|
||||
.. math::
|
||||
y = x * deq\_scale
|
||||
If `sqrt_mode` is True:
|
||||
|
||||
.. math::
|
||||
y = x * deq\_scale * deq\_scale
|
||||
|
||||
Note:
|
||||
This operation only support Ascend 310 inference environment.
|
||||
|
||||
Args:
|
||||
sqrt_mode (bool) : Specifies whether to perform square root on `scale`. Default: False.
|
||||
relu_flag (bool): Specifies whether to perform ReLU. Default: False.
|
||||
|
||||
Inputs:
|
||||
- **input_x** (Tensor) : Input tensor. Should be mindspore.int32.
|
||||
- **deq_scale** (Tensor) : Specifies the scaling ratio.
|
||||
Data type should be mindspore.float16 or mindspore.uint64
|
||||
|
||||
Outputs:
|
||||
- Tensor: The quantized output tensor of type mindspore.float16.
|
||||
|
||||
Examples:
|
||||
>>> input_x = Tensor([100.0, 150.0], mstype.float32)
|
||||
>>> dequant = P.AscendDequant(False, False)
|
||||
>>> y = dequant(input_x)
|
||||
"""
|
||||
@prim_attr_register
|
||||
def __init__(self, sqrt_mode=False, relu_flag=False):
|
||||
self.sqrt_mode = validator.check_value_type("sqrt_mode", sqrt_mode, [bool], self.name)
|
||||
self.relu_flag = validator.check_value_type("relu_flag", relu_flag, [bool], self.name)
|
||||
|
||||
def infer_shape(self, x_shape, deq_scale_shape):
|
||||
return x_shape
|
||||
|
||||
def infer_dtype(self, x_type, deq_scale_type):
|
||||
validator.check_subclass("x", x_type, mstype.tensor, self.name)
|
||||
validator.check_type_name("x", x_type, [mstype.int32], self.name)
|
||||
validator.check_type_name("deq_scale", deq_scale_type, [mstype.float16, mstype.uint64], self.name)
|
||||
return mstype.float16
|
||||
|
|
|
@ -1614,7 +1614,43 @@ test_case_other_ops = [
|
|||
|
||||
]
|
||||
|
||||
test_case_lists = [test_case_nn_ops, test_case_math_ops, test_case_array_ops, test_case_other_ops]
|
||||
|
||||
test_case_quant_ops = [
|
||||
('AscendQuant_1', {
|
||||
'block': P.AscendQuant(0.5, 0.0, False, "Round"),
|
||||
'desc_inputs': [Tensor(np.random.rand(1,2,4,4), mstype.float32)],
|
||||
'skip': ['backward']}),
|
||||
('AscendQuant_2', {
|
||||
'block': P.AscendQuant(80.0, 10.0, True, "Round"),
|
||||
'desc_inputs': [Tensor([100.0, 200.0], mstype.float32)],
|
||||
'skip': ['backward']}),
|
||||
('AscendQuant_3', {
|
||||
'block': P.AscendQuant(80.0, 0.0, False, "Floor"),
|
||||
'desc_inputs': [Tensor([100.0, 200.0], mstype.float32)],
|
||||
'skip': ['backward']}),
|
||||
('AscendQuant_4', {
|
||||
'block': P.AscendQuant(80.0, 0.0, False, "Ceil"),
|
||||
'desc_inputs': [Tensor([100.0, 200.0], mstype.float32)],
|
||||
'skip': ['backward']}),
|
||||
('AscendQuant_5', {
|
||||
'block': P.AscendQuant(80.0, 0.0, False, "Trunc"),
|
||||
'desc_inputs': [Tensor([100.0, 200.0], mstype.float32)],
|
||||
'skip': ['backward']}),
|
||||
('AscendQuant_6', {
|
||||
'block': P.AscendQuant(-80.0, 10.0, False, "Round"),
|
||||
'desc_inputs': [Tensor([100.0, 200.0], mstype.float32)],
|
||||
'skip': ['backward']}),
|
||||
('AscendQuant_7', {
|
||||
'block': P.AscendQuant(80.0, -10.0, False, "Round"),
|
||||
'desc_inputs': [Tensor([100.0, 200.0], mstype.float32)],
|
||||
'skip': ['backward']}),
|
||||
('AscendQuant_8', {
|
||||
'block': P.AscendQuant(80.0, 10.0, False, "Round"),
|
||||
'desc_inputs': [Tensor([100.0, 200.0], mstype.float16)],
|
||||
'skip': ['backward']}),
|
||||
]
|
||||
|
||||
test_case_lists = [test_case_nn_ops, test_case_math_ops, test_case_array_ops, test_case_other_ops, test_case_quant_ops]
|
||||
test_case = functools.reduce(lambda x, y: x + y, test_case_lists)
|
||||
# use -k to select certain testcast
|
||||
# pytest tests/python/ops/test_ops.py::test_backward -k LayerNorm
|
||||
|
|
Loading…
Reference in New Issue