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 866bec03ad [microNPU] Disable copying weights to SRAM for 
FullyConnected ops in CopyConstants scheduler (#13588)
866bec03ad is described below

commit 866bec03ade5dd7e4cb529cb56bd8e58b7f38326
Author: Alexey Yazev <[email protected]>
AuthorDate: Wed Dec 14 13:15:47 2022 +0400

    [microNPU] Disable copying weights to SRAM for FullyConnected ops in 
CopyConstants scheduler (#13588)
    
    In Ethos-U, CopyConstants scheduler currently copies weights for all 
operators. But in Vela, there are a number of scenarios where the weights are 
not buffered in SRAM, and FullyConnected case is one of them.
---
 python/tvm/relay/backend/contrib/ethosu/tir/scheduler.py | 10 +++++++++-
 tests/python/contrib/test_ethosu/test_scheduler.py       | 16 ++++++++++++++++
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/python/tvm/relay/backend/contrib/ethosu/tir/scheduler.py 
b/python/tvm/relay/backend/contrib/ethosu/tir/scheduler.py
index bcabe2b7c2..cee8f563ff 100644
--- a/python/tvm/relay/backend/contrib/ethosu/tir/scheduler.py
+++ b/python/tvm/relay/backend/contrib/ethosu/tir/scheduler.py
@@ -132,6 +132,12 @@ def copy_constants():
     def _planner(cached_func, const_dict, sch):
         planned = set()  # type: ignore
 
+        def _is_matmul(tensor):
+            if tensor.name not in ["ethosu_conv2d"]:
+                return False
+            a, b = tensor.op.input_tensors[0:2]
+            return a.shape[1:3] == [1, 1] and b.shape[1:3] == [1, 1]
+
         def _visit(tensor, reader, lut):
             if tensor not in planned:
                 planned.add(tensor)
@@ -140,7 +146,9 @@ def copy_constants():
                     # ambiguity when encountering a scalar.
                     is_same = [var.same_as(tensor) for var in 
cached_func.inputs]
                     index = is_same.index(True)
-                    if index in const_dict:
+                    # Along with constants, also skip for FullyConnected to 
correspond
+                    # with Vela behavior
+                    if index in const_dict and not _is_matmul(reader):
                         sch.cache_read(tensor, "global", [reader])
 
                 elif isinstance(tensor.op, tvm.te.ComputeOp):
diff --git a/tests/python/contrib/test_ethosu/test_scheduler.py 
b/tests/python/contrib/test_ethosu/test_scheduler.py
index fd1e1afa60..695aed0d19 100644
--- a/tests/python/contrib/test_ethosu/test_scheduler.py
+++ b/tests/python/contrib/test_ethosu/test_scheduler.py
@@ -217,5 +217,21 @@ def test_schedule_diamond_graph():
     tvm.ir.assert_structural_equal(test_mod["main"], reference_mod["main"], 
True)
 
 
+def test_copy_constants_fully_connected_weights():
+    """Check that MatMul-like conv2d ops do not copy weights to SRAM."""
+    ifm = relay.var("IFM", shape=(1, 1, 1, 32), dtype="int8")
+    conv = make_ethosu_conv2d(ifm, 32, 8, (1, 1), (0, 0), (1, 1), (1, 1))
+    func = relay.Function(relay.analysis.free_vars(conv), conv)
+    func = run_opt_pass(func, relay.transform.InferType())
+
+    func, const_dict = extract_constants(func)
+    cached_func = lower_to_te(func)
+
+    sch = te.create_schedule([cached_func.outputs[0].op])
+    planner = copy_constants()
+    planner(cached_func, const_dict, sch)
+    assert True not in [".global" in s.op.name for s in sch.stages]
+
+
 if __name__ == "__main__":
     pytest.main([__file__])

Reply via email to