Skip to content

Commit

Permalink
[microNPU][ETHOSU] Fix rounding mode in requantize operation (#15929)
Browse files Browse the repository at this point in the history
Before the fix, TFL rounding was used in the requantize operation and this led to a discrepancy in the results in some cases
  • Loading branch information
Aleksei-grovety authored Oct 16, 2023
1 parent a13eadb commit 0276c5a
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 5 deletions.
1 change: 1 addition & 0 deletions python/tvm/relay/backend/contrib/ethosu/legalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,7 @@ def callback(
ifm_zero_point=int(params.ifm.q_params.zero_point),
ofm_scale=float(params.ofm.q_params.scale_f32),
ofm_zero_point=int(params.ofm.q_params.zero_point),
rounding_mode="NATURAL",
)


Expand Down
18 changes: 16 additions & 2 deletions python/tvm/relay/backend/contrib/ethosu/op/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,16 @@ def create_ethosu_identity_compute(attrs, args, out_type):
ofm_scale = attrs.ofm_scale
ofm_zero_point = attrs.ofm_zero_point
activation = attrs.activation
rounding_mode = attrs.rounding_mode
op = identity_compute(
ifm, lut, ifm_scale, ifm_zero_point, ofm_scale, ofm_zero_point, activation
ifm,
lut,
ifm_scale,
ifm_zero_point,
ofm_scale,
ofm_zero_point,
activation,
rounding_mode,
)
return [op]

Expand All @@ -61,6 +69,7 @@ def ethosu_identity(
ofm_scale: float = 1,
ofm_zero_point: int = 0,
activation: str = "NONE",
rounding_mode: str = "TFL",
) -> tvm.relay.Call:
"""The Identity operator that runs on the NPU.
Expand All @@ -87,12 +96,17 @@ def ethosu_identity(
"TANH" - tanh activation function.
"SIGMOID" - sigmoid activation function.
"LUT" - use a look-up table to perform the activation function.
rounding_mode : str, optional
The rounding mode to apply to the Output Feature Map tensor.
"TFL" - Tensorflow Lite rounding scheme.
"TRUNCATE" - Truncate towards zero.
"NATURAL" - Round to nearest value, with x.5 rounded up towards +infinity.
Returns
-------
out : tvm.relay.Call
A call to the ethosu_identity op.
"""
return _make.ethosu_identity(
ifm, lut, ifm_scale, ifm_zero_point, ofm_scale, ofm_zero_point, activation
ifm, lut, ifm_scale, ifm_zero_point, ofm_scale, ofm_zero_point, activation, rounding_mode
)
8 changes: 7 additions & 1 deletion python/tvm/relay/backend/contrib/ethosu/te/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def identity_compute(
ofm_scale: float,
ofm_zero_point: int,
activation: str,
rounding_mode: str,
) -> te.Tensor:
"""A compute operator for the NPU identity operator.
Expand All @@ -54,14 +55,19 @@ def identity_compute(
"TANH" - tanh activation function.
"SIGMOID" - sigmoid activation function.
"LUT" - use a look-up table to perform the activation function.
rounding_mode : str
The rounding mode to apply to the Output Feature Map tensor.
"TFL" - Tensorflow Lite rounding scheme.
"TRUNCATE" - Truncate towards zero.
"NATURAL" - Round to nearest value, with x.5 rounded up towards +infinity.
Returns
-------
te.Tensor
The Output Feature Map tensor.
"""
dmaed_ifm = read_compute(ifm, ifm_zero_point, ifm_scale)
id_attrs = {"op": "ethosu_identity", "activation": activation}
id_attrs = {"op": "ethosu_identity", "activation": activation, "rounding_mode": rounding_mode}

has_lut = activation in ("TANH", "LUT", "SIGMOID")

Expand Down
2 changes: 1 addition & 1 deletion python/tvm/relay/backend/contrib/ethosu/tir/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ def get_identity_params(
padding=SerialPadding(0, 0, 0, 0),
activation=serial_activation,
upscale="NONE",
rounding_mode="TFL",
rounding_mode=attrs["rounding_mode"],
block_config=SerialBlockConfig(0, 0, 0),
),
output_pointer,
Expand Down
3 changes: 2 additions & 1 deletion src/relay/op/contrib/ethosu/identity.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,14 @@ bool EthosuIdentityRel(const Array<Type>& types, int num_inputs, const Attrs& at
}

Expr MakeEthosuIdentity(Expr ifm, Expr lut, double ifm_scale, int ifm_zero_point, double ofm_scale,
int ofm_zero_point, String activation) {
int ofm_zero_point, String activation, String rounding_mode) {
auto attrs = make_object<EthosuIdentityAttrs>();
attrs->ifm_scale = ifm_scale;
attrs->ifm_zero_point = ifm_zero_point;
attrs->ofm_scale = ofm_scale;
attrs->ofm_zero_point = ofm_zero_point;
attrs->activation = std::move(activation);
attrs->rounding_mode = std::move(rounding_mode);
static const Op& op = Op::Get("contrib.ethosu.identity");
return Call(op, {ifm, lut}, Attrs(attrs), {});
}
Expand Down
8 changes: 8 additions & 0 deletions src/relay/op/contrib/ethosu/op_attrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ struct EthosuIdentityAttrs : public tvm::AttrsNode<EthosuIdentityAttrs> {
double ofm_scale;
int ofm_zero_point;
String activation;
String rounding_mode;

TVM_DECLARE_ATTRS(EthosuIdentityAttrs, "relay.attrs.EthosuIdentityAttrs") {
TVM_ATTR_FIELD(ifm_scale).describe("The quantization scale for the Input Feature Map tensor.");
Expand All @@ -335,6 +336,13 @@ struct EthosuIdentityAttrs : public tvm::AttrsNode<EthosuIdentityAttrs> {
"'SIGMOID' - sigmoid activation function. "
"'LUT' - use a look-up table to perform the activation function.")
.set_default("NONE");
TVM_ATTR_FIELD(rounding_mode)
.describe(
"The rounding mode to apply to the Output Feature Map tensor. "
"'TFL' - Tensorflow Lite rounding scheme. "
"'TRUNCATE' - Truncate towards zero."
"'NATURAL' - Round to nearest value, with x.5 rounded up towards +infinity.")
.set_default("TFL");
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def test_ethosu_identity_matcher():
ofm_scale=1,
ofm_zero_point=0,
activation="NONE",
rounding_mode="TFL",
)

length = len(ifm.shape)
Expand Down
1 change: 1 addition & 0 deletions tests/python/contrib/test_ethosu/test_codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -1233,6 +1233,7 @@ def split_func(x):
[
[(1, 8, 8, 3), 1.0, 0, 1.0, 0],
[(1, 20, 30, 3), 1.345, 34, 0.32, -23],
[(1, 1, 4, 8), 0.0078125, 0, 0.00997, -30],
],
)
def test_ethosu_requantize(accel_type, ifm_shape, ifm_scale, ifm_zp, ofm_scale, ofm_zp):
Expand Down

0 comments on commit 0276c5a

Please sign in to comment.