[TVM Discuss] [Development] Missing memoization in ExprFunctor

2020-04-11 Thread masahi via TVM Discuss


Currently I'm about to merge a PR 
https://github.com/apache/incubator-tvm/pull/5310 which adds memoization logic 
for `ExprFunctor` in two different derived classes. 

I've also noticed that there are many places in the code base that have the 
same duplicated memoization logic for `ExprFunctor`, e.g
https://github.com/apache/incubator-tvm/blob/00014e20c3cc077727d467a67d3498260627e4e0/src/relay/backend/compile_engine.cc#L182-L191
https://github.com/apache/incubator-tvm/blob/00014e20c3cc077727d467a67d3498260627e4e0/src/relay/backend/graph_runtime_codegen.cc#L320

Since `ExprMutator` does have a memo built in, I wonder why `ExprFunctor` 
doesn't have it as well? I think we can clean up existing derived classes a 
lot. Is there a deep reason `ExprFunctor` cannot have a built in memoization?

Since `ExprFunctor` doesn't have memo, derived classes need to override 
`VisitExpr(const Expr& expr)` method and implement dispatching logic as well, 
in addition to memo logic.  

I think it is a good item to add to our refactoring effort. cc @tqchen @zhiics





---
[Visit 
Topic](https://discuss.tvm.ai/t/missing-memoization-in-exprfunctor/6334/1) 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/e2fa975829637e4beff312a9d78930585064fe2950ed3a514467eacf3aa9f023).


[TVM Discuss] [Development] Missing memoization in ExprFunctor

2020-04-11 Thread tqchen via TVM Discuss


ExprFunctor is a more generic base class for dispatching, while itself can be 
used to build recursive visitors, the visitor is not the only use case for the 
ExprFunctor. For example, we use the functor to build a dispatching Rewriter 
callbacks in the recent non-recursive vistor.

Memoization  could also have un-desired cosquences, if the translation depends 
on the context(e.g. if you are in the if and else branch, the results might be 
different).

Due to these considerations, it is better to allow "no-surprise" and leave 
functors as simple as possible(thus no memoization)





---
[Visit 
Topic](https://discuss.tvm.ai/t/missing-memoization-in-exprfunctor/6334/2) 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/0ce4d8bc426f77d742394ef23a6f23d3c3efc54db3fc6ea47fea3bb874711ab0).


[TVM Discuss] [Development] Missing memoization in ExprFunctor

2020-04-11 Thread masahi via TVM Discuss


hmm, then does it make sense to have a another derived class, say 
`MemoizedExprFunctor`, that does have a memo logic built in, for a simple use 
case in derived classes that requires memoization? The PR I saw today could 
derive from this instead of ExprFunctor, for example.

Basically for encapsulating already duplicated logics in our codebase. The rest 
of code that needs more care are not going to be affected.





---
[Visit 
Topic](https://discuss.tvm.ai/t/missing-memoization-in-exprfunctor/6334/3) 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/81affa1ec89201499c28a39a143dfd3f9b88261fa0c652e4dcf1938a4e3c72a2).


[TVM Discuss] [Development] Missing memoization in ExprFunctor

2020-04-11 Thread tqchen via TVM Discuss


Given that the ExprFunctor also have additional arguments(besides the first 
argument), it is unclear how do we define such Memoization, unless we restrict 
the arguments to only contain the single one.  The addtional cost for memo is 
not taking a lot of locs, so I think either way is fine(considering the 
tradeoff between reuse vs reduce the layer of abstractions)





---
[Visit 
Topic](https://discuss.tvm.ai/t/missing-memoization-in-exprfunctor/6334/4) 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/a01632345beed5e269861965dad36607e530cc26d1bb54eb9ccea080e8147640).


[TVM Discuss] [Development] Missing memoization in ExprFunctor

2020-04-11 Thread masahi via TVM Discuss


[quote="tqchen, post:4, topic:6334"]
The addtional cost for memo is not taking a lot of locs
[/quote]

Note that in addition to the memo logic itself, we can also remove 
`VisitExpr(const Expr& expr)` override in the derived classes (which to me 
seems only exist for memoization), and hence the dispatching logic like this 
can be also removed:

https://github.com/apache/incubator-tvm/blob/00014e20c3cc077727d467a67d3498260627e4e0/src/relay/backend/graph_runtime_codegen.cc#L322-L352

I think this dispatching logic is already handled by `ExprFunctor`. So if the 
base class has memo logic built in, dervied classes don't need to 
`VisitExpr(const Expr& expr)` override at all. The PR 
https://github.com/apache/incubator-tvm/pull/5310/ also has this dispatch logic 
in `VisitExpr(const Expr& expr)` override.

Moreover, without memoization in the base class, all external codegen (most of 
which is not public and hence we don't know how many) needs to implement 
memoization in the codegen backend. I actually hit "exponential blow up" error 
when compiling resnet with my codegen because I was missing memoization. So I 
think reuse opportunity of memoization in the base class is high.

[quote="tqchen, post:4, topic:6334"]
Given that the ExprFunctor also have additional arguments(besides the first 
argument), it is unclear how do we define such Memoization, unless we restrict 
the arguments to only contain the single one.
[/quote]

It seems all use of `ExprFunctor` in the code base that adds memoization on top 
takes a single `const Expr&` argument, so I think single argument restriction 
is reasonable.

So given these reason I think cost-to-benefit ratio of adding  
`MemoziedExprFunctor` is in favor. Anyway I'll send a PR and we can decide if 
it is a good addition.





---
[Visit 
Topic](https://discuss.tvm.ai/t/missing-memoization-in-exprfunctor/6334/5) 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/b19317774a274dce86a82992d7cacc10e7ea43a3c21bc9b26e308fe22543de27).


[TVM Discuss] [Development/RFC] [RFC] Visualizing Relay program as graph

2020-04-11 Thread JC Li via TVM Discuss


Thanks for the great proposal. @hcho3, I followed your [script in 
github](https://github.com/hcho3/relayviz) and noticed it missed a case when 
operator being "Call"ed is a function.  

Adding some code within "Call" condition can generate graph with each function 
singled out. 

```
elif isinstance(node, tvm.relay.expr.Call):
args = [node_dict[arg] for arg in node.args]
if isinstance(node.op, tvm.relay.Function):
print(f'node_idx: {node_idx}, 
Call(Function({node_dict[node.op.body]}))')
dot.node(str(node_idx), 
f'Call(Function({node_dict[node.op.body]}))')
else:
print(f'node_idx: {node_idx}, Call(op_name={node.op.name}, 
args={args})')
dot.node(str(node_idx), f'Call(op={node.op.name})')
for arg in args:
dot.edge(str(arg), str(node_idx))
elif isinstance(node, tvm.relay.Function):
print(f'node_idx: {node_idx}, 
Function(body={node_dict[node.body]})')
dot.node(str(node_idx), f'Function'+str({node_dict[node.body]}))
dot.edge(str(node_dict[node.body]), str(node_idx))
```
![relay_graph|690x150](upload://dE1sridGzQo19Qm9tLjqkzRfc0l.png)





---
[Visit 
Topic](https://discuss.tvm.ai/t/rfc-visualizing-relay-program-as-graph/4825/15) 
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/7bcc544c68d3e2a08eb015089fecb9db2bf1122c769665014c89432917f27519).