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):

Reply via email to