You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by "lhutton1 (via GitHub)" <gi...@apache.org> on 2023/01/27 13:06:51 UTC

[GitHub] [tvm] lhutton1 commented on a diff in pull request #13212: [TVMC][microNPU] tvmc option for printing which operators are offloaded to Ethos-U

lhutton1 commented on code in PR #13212:
URL: https://github.com/apache/tvm/pull/13212#discussion_r1086482503


##########
python/tvm/driver/tvmc/compiler.py:
##########
@@ -459,3 +489,79 @@ def save_dumps(module_name: str, dumps: Dict[str, str], dump_root: str = "."):
         dump_name = module_name + "." + dump_format
         with open(Path(dump_root, dump_name), "w") as f:
             f.write(dumps[dump_format])
+
+
+def dump_operation_offloads(mod: tvm.ir.IRModule, initial_mod: tvm.ir.IRModule, dump_path: str):
+    """This helper function forms a line-by-line output of the initial Relay lines,
+    indicating which operations are ported to which target,
+    and indicating the composite that includes those operations;
+    the 'generic' target refers to operations uploaded to the host, e.g
+    'target1        <-     target2.qnn_conv2d'

Review Comment:
   nit: `target2.qnn_conv2d` -> `target1.qnn_conv2d`



##########
python/tvm/relay/analysis/operations_distribution.py:
##########
@@ -0,0 +1,86 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""Utilities that enable analyze Relay and get mappings for unique
+input module layer name to the tuple of compiler and operation name"""
+import tvm
+from tvm import relay
+from tvm.relay.expr_functor import ExprVisitor
+
+
+class AnalyzeOperationsDistribution(ExprVisitor):

Review Comment:
   Thanks, could we also add a test for the generic only fallback case?



##########
python/tvm/relay/frontend/common.py:
##########
@@ -1067,6 +1067,20 @@ def __init__(self, span):
             self._span = tvm.relay.Span(tvm.relay.SourceName(span.decode("utf-8")), 0, 0, 0, 0)
         else:
             assert False, f"unsupported span type: {type(span)}"
+        self.suffix_str = "_PART_"
+        self.counter = 0
+        self.distance_from_leaf = -1
+
+    def _create_span(self):
+        """Adds suffix_str + counter value to _span.source_name.name,
+        to create a unique source_name for the Relay layer
+        """
+        if self.distance_from_leaf == 0:
+            return tvm.relay.Span(tvm.relay.SourceName(self._span), 0, 0, 0, 0)
+        self.distance_from_leaf -= 1
+        span_str = "{}{}{}".format(self._span.source_name.name, self.suffix_str, str(self.counter))
+        self.counter += 1
+        return tvm.relay.Span(tvm.relay.SourceName(span_str), 0, 0, 0, 0)

Review Comment:
   This seems sensible to me, cc the original author of span filling @chunit-quic just to check
   
   Is `self.counter` required, or can the same info already be fetched from `self.distance_from_leaf` e.g. `.format(..., str(-self.distance_from_leaf))`?



##########
tests/python/contrib/test_ethosu/test_pass_operations_distribution.py:
##########
@@ -0,0 +1,84 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from tvm.relay.analysis.operations_distribution import analyze_operations_distribution
+from . import infra
+import pytest
+import numpy as np
+
+
+def test_operations_distribution():
+
+    tflite = pytest.importorskip("tflite")
+    tensorflow = pytest.importorskip("tensorflow")
+    pytest.importorskip("ethosu.vela")
+
+    import tensorflow as tf
+
+    inp = (224, 224, 9)
+    input_shape = (1, *inp)
+    kernel_shape = (3, 3)
+    padding = (1, 1, 1, 1)
+    padding_out = (1, 33, 33, 1)
+
+    @tf.function
+    def simple_net(x):
+        weight_shape = [kernel_shape[0], kernel_shape[1], input_shape[3], 3]
+        weights = tf.constant(np.random.uniform(size=weight_shape), dtype=tf.float32)
+        op = tf.nn.conv2d(
+            x,
+            filters=weights,
+            strides=1,
+            padding="SAME",
+            data_format="NHWC",
+            dilations=1,
+        )
+        op = tf.pad(
+            op,
+            [[0, 0], [padding[0], padding_out[2]], [padding_out[1], padding[3]], [0, 0]],
+            "CONSTANT",
+        )
+        op = tf.pad(
+            op,
+            [[0, 0], [padding[0], padding[2]], [padding[1], padding[3]], [0, 0]],
+            "CONSTANT",
+        )
+        return tf.pad(
+            op,
+            [[0, 0], [padding_out[0], padding[2]], [padding[1], padding_out[3]], [0, 0]],
+            "CONSTANT",
+        )
+
+    from tests.python.contrib.test_ethosu.infra import get_tflite_graph
+
+    mod, params = infra.get_tflite_graph(simple_net, [input_shape])
+
+    operations_distribution = analyze_operations_distribution(mod)
+
+    expected = {
+        "Pad_PART_0": ["generic", "generic", 0],
+        "Conv2D2_PART_2": ["ethos-u", "ethos-u.qnn_conv2d", 1],
+        "Conv2D2_PART_1": ["ethos-u", "ethos-u.qnn_conv2d", 1],
+        "Conv2D2_PART_0": ["ethos-u", "ethos-u.qnn_conv2d", 1],
+        "Identity_PART_0": ["ethos-u", "ethos-u.pad2d", 2],

Review Comment:
   Out of interest, what makes this pad op get called `identity`?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org