I think main topic of interest here is the way we define function signatures, 
not necessarily how to broaden the scope of the same function to support more 
flexible inputs(e.g. `Any`)

I think the main goal of A1 concerns the  semantics of the attribute. Since 
attribute has always been considered as constant and can be used during shape 
inference.

The main difference between A0 and A1 are not about how do we categorize 
dynamic ops vs static ops, all the operator still will need to support the type 
inference `Any`, as you suggested. It only has to do with the way we define 
operators.

For example, in the context of the reshape operator, A1 means we will have two 
variants of operators:
- A1:
   - V0: relay.static.reshape(x, attr={shape: (1,2,3)})
   - V1: relay.dyn.reshape(x, shape)
   - relay.reshape alias to V0 for now for backward compact, once the dyn -> 
static pass completes, relay.reshape alias to relay.dyn.reshape.
- A0: For a clear comparison this is the V2 variants.
   - V2: relay.reshape(x, shape, optional_attr={shape: (1,2,3)})

Both V0 and V1 still need to be able to handle the case of `Any` in the 
input(x), in the case of V1, it also need to handle `Any` in terms of the 
shape. In the same case (A0) V2 also need to handle `Any` in all of its input. 

There is a  tension between frontend and the backends. For frontends, it is 
easier to use operator signatures that are more "dynamic". For backend, 
however, we want more information in the system, which favors more static 
information as part of the function signature. The type inference can certainly 
take benefit of the attribute information of the operator. Because attribute is 
constant and directly available during type inference. So besides introducing 
V1 style operator def, it is important to have a pass to be able to convert 
dynamic variants of operators aka V1 into V0 when possible, so that even though 
the input graph has a dynamic semantics, we will still be able to use static 
information in the case of graph runtime and embedded devices.

The definition of V2 is trying to combine V0, V1 s  a polymorphic function into 
a single function signature. In terms of implementations, it means that during 
the optimizations passes, a pass would have to deal with all possible 
combinations of V2, (e.g. shape_attr exists, shape exists, both exists). It is 
harder for pass writer to understands the semantics of the operator, as the 
same piece of information is available in two possible places.

The advantage of A1 is the separation of concern. The frontend can always use 
V1 to import the model. Of course A1 does not reduce the amount of effort, 
since most effort done in V2 would need to be split into two natural part of 
functions to support V0 and V1. It does makes the dyn to static conversion pass 
easier, so that output of the pass contains as many ops in V0 style as 
possible, and optimization passes that targets these static variants of ops can 
be used to provide better optimization chances for the backend.





---
[Visit Topic](https://discuss.tvm.ai/t/dynamic-ops-in-relay/6909/6) to respond.

You are receiving this because you enabled mailing list mode.

To unsubscribe from these emails, [click 
here](https://discuss.tvm.ai/email/unsubscribe/9dc5728971517b69ebc442a732bf2395600b7ac2ead4c121e78aec37ea346c91).

Reply via email to