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 6ebb0fd1ad [ETHOSN] Fix output tensor ordering (#12317)
6ebb0fd1ad is described below
commit 6ebb0fd1ad35948c155b56d857392146cb168319
Author: Luke Hutton <[email protected]>
AuthorDate: Mon Aug 8 17:08:53 2022 +0100
[ETHOSN] Fix output tensor ordering (#12317)
During compilation of an NPU subgraph, the input and output tensor
ordering is determined by creating a mapping of Support Library
buffers to TVM buffers. The runtime had been using this mapping
incorrectly by instead interpreting it as a mapping of TVM buffers to
support library buffers. This can result in undefined behaviour. The
runtime now interprets the mapping as Support Library buffers to TVM
buffers.
A test has been added to check the correct ordering of outputs is
provided correctly in the runtime.
---
src/runtime/contrib/ethosn/ethosn_device.cc | 6 +--
.../python/contrib/test_ethosn/test_topologies.py | 46 ++++++++++++++++++++++
2 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/src/runtime/contrib/ethosn/ethosn_device.cc
b/src/runtime/contrib/ethosn/ethosn_device.cc
index 4adecfd4df..348a550460 100644
--- a/src/runtime/contrib/ethosn/ethosn_device.cc
+++ b/src/runtime/contrib/ethosn/ethosn_device.cc
@@ -119,16 +119,16 @@ bool Inference(tvm::runtime::TVMArgs args, dl::Network*
npu,
const std::vector<uint32_t>& output_sizes) {
#endif
// Unpack parameters
- uint8_t argc = 0;
size_t n_inputs = input_order.size();
size_t n_outputs = output_order.size();
std::vector<DLTensor*> inputs(n_inputs);
for (uint8_t i = 0; i < n_inputs; i++) {
- inputs[input_order[i]] = args[argc++];
+ inputs[i] = args[input_order[i]];
}
std::vector<DLTensor*> outputs(n_outputs);
+ size_t output_offset = n_inputs;
for (uint8_t i = 0; i < n_outputs; i++) {
- outputs[output_order[i]] = args[argc++];
+ outputs[i] = args[output_order[i] + output_offset];
}
// Set up input buffers
diff --git a/tests/python/contrib/test_ethosn/test_topologies.py
b/tests/python/contrib/test_ethosn/test_topologies.py
index 5a1dce4b39..8f8c353de2 100644
--- a/tests/python/contrib/test_ethosn/test_topologies.py
+++ b/tests/python/contrib/test_ethosn/test_topologies.py
@@ -182,6 +182,52 @@ def test_output_order(dtype):
tei.verify(outputs, dtype, 1)
+@requires_ethosn
[email protected]("dtype", ["uint8", "int8"])
+def test_output_order_different_sizes(dtype):
+ """
+ Test the output order when there are multiple outputs of different sizes.
+ """
+ np.random.seed(0)
+ input_name = "a"
+ input_shape = (1, 8, 8, 4)
+ dtype_min = np.iinfo(dtype).min
+ dtype_max = np.iinfo(dtype).max
+
+ def get_model():
+ var = relay.var(input_name, shape=input_shape, dtype=dtype)
+ clip = relay.op.clip(var, dtype_min, dtype_max)
+ max_pool = relay.nn.max_pool2d(clip, (2, 2), (2, 2), ceil_mode=True,
layout="NHWC")
+ mean = relay.op.cast(clip, "int32")
+ mean = relay.mean(mean, axis=[1, 2], keepdims=True)
+ mean = relay.qnn.op.requantize(
+ mean,
+ input_scale=relay.const(0.0784314, "float32"),
+ input_zero_point=relay.const(dtype_min + 128, "int32"),
+ output_scale=relay.const(0.0784314, "float32"),
+ output_zero_point=relay.const(dtype_min + 128, "int32"),
+ out_dtype=dtype,
+ )
+
+ return relay.Tuple((mean, max_pool, clip))
+
+ inputs = {
+ input_name: tvm.nd.array(
+ np.random.randint(dtype_min, dtype_max + 1, size=input_shape,
dtype=dtype)
+ ),
+ }
+
+ outputs = []
+ for npu in [False, True]:
+ model = get_model()
+ mod = tei.make_module(model, [])
+ outputs.append(
+ tei.build_and_run(mod, inputs, 3, {}, npu=npu,
expected_host_ops=0, npu_partitions=1)
+ )
+
+ tei.verify(outputs, dtype, 1)
+
+
@requires_ethosn
@pytest.mark.parametrize("dtype", ["uint8", "int8"])
def test_split_with_asym_concats(dtype):