You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by lu...@apache.org on 2022/08/23 13:28:20 UTC
[tvm] branch main updated: [ETHOSN] Fix requantize output conversion (#12540)
This is an automated email from the ASF dual-hosted git repository.
lukhut pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git
The following commit(s) were added to refs/heads/main by this push:
new ff46fa15e0 [ETHOSN] Fix requantize output conversion (#12540)
ff46fa15e0 is described below
commit ff46fa15e063ef499f666e63b9d5ed3faf2e3bfb
Author: Luke Hutton <lu...@arm.com>
AuthorDate: Tue Aug 23 14:28:12 2022 +0100
[ETHOSN] Fix requantize output conversion (#12540)
Fixes a small issue when converting the output information to the support library API. The `requantize_info` output datatype needed updating with the output datatype from the relay function to ensure the graph is compiled correctly by the support library. Included a test to prevent regression in the future.
---
src/relay/backend/contrib/ethosn/ethosn_api.cc | 22 ++++----
.../python/contrib/test_ethosn/test_requantize.py | 63 ++++++++++++++++++++++
2 files changed, 75 insertions(+), 10 deletions(-)
diff --git a/src/relay/backend/contrib/ethosn/ethosn_api.cc b/src/relay/backend/contrib/ethosn/ethosn_api.cc
index c828762096..55d0b57bcc 100644
--- a/src/relay/backend/contrib/ethosn/ethosn_api.cc
+++ b/src/relay/backend/contrib/ethosn/ethosn_api.cc
@@ -678,11 +678,17 @@ EthosnError EthosnAPI::Relu(const Expr& expr, ReluParams* params) {
EthosnError EthosnAPI::Requantize(const Expr& expr, RequantizeParams* params) {
Call call = Downcast<Call>(expr);
- const auto* input_dtype = call->args[0]->checked_type().as<TensorTypeNode>();
+ const auto* input_ttype = call->args[0]->checked_type().as<TensorTypeNode>();
sl::TensorShape input_tensor_shape = {1, 1, 1, 1};
sl::DataType input_data_type;
- EthosnError err = Tvm2Npu(input_dtype->shape, &input_tensor_shape);
- err += Tvm2Npu(input_dtype->dtype, &input_data_type);
+ EthosnError err = Tvm2Npu(input_ttype->shape, &input_tensor_shape);
+ err += Tvm2Npu(input_ttype->dtype, &input_data_type);
+
+ const auto* output_ttype = call->checked_type().as<TensorTypeNode>();
+ sl::TensorShape output_tensor_shape = {1, 1, 1, 1};
+ sl::DataType output_data_type;
+ err += Tvm2Npu(output_ttype->shape, &output_tensor_shape);
+ err += Tvm2Npu(output_ttype->dtype, &output_data_type);
float input_sc, output_sc;
int input_zp, output_zp;
@@ -699,14 +705,10 @@ EthosnError EthosnAPI::Requantize(const Expr& expr, RequantizeParams* params) {
sl::QuantizationInfo requantize_q_info;
err += Tvm2Npu(output_zp, output_sc, &requantize_q_info);
params->requantize_info = sl::RequantizeInfo(requantize_q_info);
+ params->requantize_info.m_OutputDataType = output_data_type;
- sl::TensorInfo output_info = params->input_info;
- output_info.m_QuantizationInfo = params->requantize_info.m_OutputQuantizationInfo;
- if (params->requantize_info.m_OutputDataType.has_value()) {
- output_info.m_DataType = params->requantize_info.m_OutputDataType.value();
- }
- params->output_info = output_info;
-
+ params->output_info = sl::TensorInfo(output_tensor_shape, output_data_type, sl::DataFormat::NHWC,
+ requantize_q_info);
return err;
}
diff --git a/tests/python/contrib/test_ethosn/test_requantize.py b/tests/python/contrib/test_ethosn/test_requantize.py
index 4626a0d92b..e20c3beeab 100644
--- a/tests/python/contrib/test_ethosn/test_requantize.py
+++ b/tests/python/contrib/test_ethosn/test_requantize.py
@@ -68,6 +68,69 @@ def test_requantize(in_dtype, out_dtype, shape):
tei.verify(outputs, out_dtype, 1)
+@requires_ethosn
+def test_requantize_mixed_precision_with_following_op():
+ """
+ Checks a requantize operation that changes precision from uint8 to int8 with a
+ following add op.
+ """
+ np.random.seed(0)
+ shape = (1, 4, 6, 8)
+ in_sc = 0.012566
+ in_zp = 131
+ out_sc = 0.012566
+ out_zp = 3
+ in_dtype = "uint8"
+ out_dtype = "int8"
+
+ def get_model():
+ a = relay.var("a", shape=shape, dtype=in_dtype)
+ b = relay.var("b", shape=shape, dtype=out_dtype)
+ req = relay.qnn.op.requantize(
+ data=a,
+ input_scale=relay.const(in_sc, "float32"),
+ input_zero_point=relay.const(in_zp, "int32"),
+ output_scale=relay.const(out_sc, "float32"),
+ output_zero_point=relay.const(out_zp, "int32"),
+ out_dtype=out_dtype,
+ )
+ req = relay.qnn.op.add(
+ req,
+ b,
+ lhs_scale=relay.const(out_sc, "float32"),
+ lhs_zero_point=relay.const(out_zp, "int32"),
+ rhs_scale=relay.const(out_sc, "float32"),
+ rhs_zero_point=relay.const(out_zp, "int32"),
+ output_scale=relay.const(out_sc, "float32"),
+ output_zero_point=relay.const(out_zp, "int32"),
+ )
+ return req
+
+ inputs = {
+ "a": tvm.nd.array(
+ np.random.randint(
+ low=np.iinfo(in_dtype).min, high=np.iinfo(in_dtype).max, size=shape, dtype=in_dtype
+ )
+ ),
+ "b": tvm.nd.array(
+ np.random.randint(
+ low=np.iinfo(out_dtype).min,
+ high=np.iinfo(out_dtype).max,
+ size=shape,
+ dtype=out_dtype,
+ )
+ ),
+ }
+ outputs = []
+ for npu in [False, True]:
+ model = get_model()
+ mod = tei.make_module(model, {})
+ x = tei.build_and_run(mod, inputs, 1, {}, npu=npu)
+ outputs.append(x)
+
+ tei.verify(outputs, out_dtype, 1)
+
+
@requires_ethosn
def test_requantize_failure():
input_sc = 0.8