You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by GitBox <gi...@apache.org> on 2022/04/21 16:12:24 UTC

[GitHub] [tvm] ekalda commented on a diff in pull request #10509: [microNPU] Add various options to the cascader

ekalda commented on code in PR #10509:
URL: https://github.com/apache/tvm/pull/10509#discussion_r855153477


##########
python/tvm/contrib/ethosu/cascader/block_config.py:
##########
@@ -45,5 +45,17 @@ def compute_cycles(self) -> int:
     def output_cycles(self) -> int:
         return int(self._output_cycles)
 
+    def __ge__(self, other: "BlockConfig"):
+        if len(self.output_shape) != len(other.output_shape):
+            return False
+
+        return all(a >= b for a, b in zip(self.output_shape, other.output_shape))
+
+    def __lt__(self, other: "BlockConfig"):
+        if len(self.output_shape) != len(other.output_shape):
+            return False
+
+        return other >= self

Review Comment:
   Is it supposed to be similar to the comparison in `__ge__`?



##########
python/tvm/contrib/ethosu/cascader/scheduler.py:
##########
@@ -169,13 +172,19 @@ def create_home_map(
     return home_map
 
 
-def choose_proposal(proposals: List[Proposal], cascade_region: MemoryRegion):
+def choose_proposal(
+    proposals: List[Proposal], cascade_region: MemoryRegion, select_proposal_idx: int
+):
     """Choose the best performing Proposal that doesn't overflow the cascade region."""
-    proposal_choice = proposals[0]
-    for proposal in reversed(proposals):
-        if proposal.memory_usage < cascade_region.size:
-            proposal_choice = proposal
-            break
+    if select_proposal_idx != -1:
+        # Manually select proposal based on index
+        proposal_choice = proposals[select_proposal_idx % len(proposals)]

Review Comment:
   What is the `% len(proposals)` for?



##########
tests/python/contrib/test_ethosu/cascader/test_plan_generator.py:
##########
@@ -47,7 +46,98 @@ def test_generate_output_stripe_configs():
     tensor_1.add_consumer(part_1)
     tensor_2.add_producer(part_1)
 
-    assert len(_generate_output_stripe_configs(part_1, stripe_factors)) == expected_configs
+    expected_stripe_configs = {
+        cs.StripeConfig([1, 1], [400, 400], [1, 1], [1, 2], [400, 400], [0, 0]),
+        cs.StripeConfig([1, 1], [400, 400], [1, 1], [2, 1], [400, 400], [0, 0]),
+        cs.StripeConfig([200, 1], [400, 400], [200, 1], [1, 2], [2, 400], [0, 0]),
+        cs.StripeConfig([200, 1], [400, 400], [200, 1], [2, 1], [2, 400], [0, 0]),
+        cs.StripeConfig([400, 1], [400, 400], [400, 1], [2, 1], [1, 400], [0, 0]),
+        cs.StripeConfig([1, 200], [400, 400], [1, 200], [1, 2], [400, 2], [0, 0]),
+        cs.StripeConfig([1, 200], [400, 400], [1, 200], [2, 1], [400, 2], [0, 0]),
+        cs.StripeConfig([200, 200], [400, 400], [200, 200], [2, 1], [2, 2], [0, 0]),
+        cs.StripeConfig([200, 200], [400, 400], [200, 200], [1, 2], [2, 2], [0, 0]),
+        cs.StripeConfig([400, 200], [400, 400], [400, 200], [2, 1], [1, 2], [0, 0]),
+        cs.StripeConfig([1, 400], [400, 400], [1, 400], [1, 2], [400, 1], [0, 0]),
+        cs.StripeConfig([200, 400], [400, 400], [200, 400], [1, 2], [2, 1], [0, 0]),
+        cs.StripeConfig([400, 400], [400, 400], [400, 400], [1, 2], [1, 1], [0, 0]),
+    }
+
+    output_stripe_configs = _generate_output_stripe_configs(
+        part=part_1, stripe_factors=stripe_factors, multi_dimensional=True
+    )
+
+    assert len(output_stripe_configs) == len(expected_stripe_configs)
+    assert set(output_stripe_configs) == expected_stripe_configs

Review Comment:
   I think it would be good to have some tests for the various culling disabling options. Is it possible to compare sets of plans, proposals or block configs similarly to how it is done here for the stripe configs? In that case we could have similar regressions tests for non optimal proposals, plans and block configs.



##########
src/relay/backend/contrib/ethosu/compiler_attrs.cc:
##########
@@ -39,13 +39,53 @@ namespace ethosu {
 /*! \brief Attributes to store the compiler options for Arm(R) Ethos(TM)-U NPU. */
 struct EthosUCompilerConfigNode : public tvm::AttrsNode<EthosUCompilerConfigNode> {
   String accelerator_config;
+  String dev_force_block_config;
+  String dev_max_open_plans;
+  String dev_max_closed_plans;
+  String dev_select_proposal_idx;
+  bool dev_disable_pareto_plans;
+  bool dev_disable_pareto_proposals;
+  bool dev_disable_block_culling;
+  bool dev_cascader_logging;
 
   TVM_DECLARE_ATTRS(EthosUCompilerConfigNode, "ext.attrs.EthosUCompilerConfigNode") {
     TVM_ATTR_FIELD(accelerator_config)
         .describe(
             "The class of Arm(R) Ethos(TM)-U NPU; possible values = {ethos-u55-32, ethos-u55-64, "
             "ethos-u55-128, ethos-u55-256}")
         .set_default("ethos-u55-256");
+    String dev_warning = "Option is intended for development and debugging purposes only. ";
+    TVM_ATTR_FIELD(dev_force_block_config)
+        .describe(
+            "Force the block config to a given value; format = "
+            "\"[BLK_HEIGHT]x[BLK_WIDTH]x[BLK_DEPTH]\"")
+        .set_default("");

Review Comment:
   Should that dev option also also come with a `dev_warning`?



##########
src/contrib/ethosu/cascader/pareto.h:
##########
@@ -65,9 +65,11 @@ std::vector<T> ThinVector(const std::vector<T>& vec, size_t max_size);
  * \note Plan Pareto-optimality is determined based upon a Plan's memory_usage
  * and cycles.
  */
-std::vector<Plan> ParetoCullPlans(std::vector<Plan> plans, size_t max_plans);
+std::vector<Plan> ParetoCullPlans(std::vector<Plan> plans, size_t max_plans,
+                                  bool disable_pareto_metric);

Review Comment:
   nit: add documentation to `disable_pareto_metric`



##########
python/tvm/contrib/ethosu/cascader/device_config.py:
##########
@@ -491,6 +493,28 @@ def get_elementwise_block_config(
         if activation == "LUT" and not self._lut_reserved:
             banks_available -= 2
 
+        # Handle user-forced block config
+        options = tvm.transform.PassContext.current().config.get("relay.ext.ethos-u.options", None)
+        if options and options.dev_force_block_config:
+            block_config = [int(v) for v in options.dev_force_block_config.split("x")]
+            assert len(block_config) == 3
+            if output_layout == "NHWC":
+                block_shape = [output_shape[0], block_config[0], block_config[1], block_config[2]]
+            else:
+                block_shape = [
+                    output_shape[0],
+                    block_config[0],
+                    1 + ((block_config[2] - 1) // 16),
+                    block_config[1],
+                    16,
+                ]
+            output_cycles = self._get_output_cycles(
+                op_type, op_str, ifm_dtype, ofm_dtype, activation
+            )
+            output_cycles *= reduce(lambda a, b: a * b, block_shape, 1)

Review Comment:
   Maybe `np.prod(block_shape)` for simplicity



##########
src/contrib/ethosu/cascader/cascader_options.h:
##########
@@ -47,8 +47,20 @@ class CascaderOptionsNode : public Object {
   int stripe_factors;
   /*! \brief The maximum number of Parts in a Plan. */
   int max_plan_size;
+  /*! \brief The maximum number of open Plans saved for a Part Group */
+  int max_open_plans;
+  /*! \brief The maximum number of closed Plans saved for a Part Group */
+  int max_closed_plans;
   /*! \brief The maximum size of Tensor that will always be copied into the cascade region. */
   int always_copy_size;
+  /*! \brief Flag to disable pareto culling for plans to allow non pareto-optimal plans */
+  bool disable_pareto_plans;
+  /*! \brief Flag to disable pareto culling for proposals to allow non pareto-optimal proposals */
+  bool disable_pareto_proposals;
+  /*! \brief Whether to consider multi-dimensional striping */
+  bool multi_dimensional_striping;

Review Comment:
   nit: maybe `enable_multi_dimensional_striping` to match with other similar variables



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