-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Relay] Partial Eval now Support Interprocedural optimization and has termination check. #3033
Conversation
@tqchen can you give another round of review? |
@MarisaKirisame please rebase. @wweic @jroesch please help review this PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some general cents. will do more detailed review in the next few days.
@@ -220,8 +220,8 @@ TVM_REGISTER_API("relay._make.Call") | |||
|
|||
TVM_STATIC_IR_FUNCTOR_REGISTER(IRPrinter, vtable) | |||
.set_dispatch<CallNode>([](const CallNode* node, tvm::IRPrinter* p) { | |||
p->stream << "CallNode(" << node->op << ", " << node->args << ", " | |||
<< node->attrs << ", " << node->type_args << ")"; | |||
p->stream << "CallNode(" << node->op << ", " << node->args << ", " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better use the command in https://github.com/dmlc/tvm/blob/master/.clang-format to do the formatting so we maintain a consistent code style. The indentation style is 2 space I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not work - the result is completely different from all other files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably due to we use different rules for macro.
src/relay/pass/partial_eval.cc
Outdated
private: | ||
Environment env_; | ||
Module mod_; | ||
std::unordered_map<GlobalVar, PStatic, NodeHash, NodeEqual> gv_map_; | ||
/*! Termination checking is done as follow: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a test that verifies termination checking(no infinite loop)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is test_map and test_loop. However, none of the test is working right now as the vm merge break this. I will fix them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are fixed.
note to self: dead code elimination dont do inline, so we need an inline pass to make test work again. |
@nhynes @icemelon9 can you guys help review? |
@tqchen @jroesch @slyubomirsky can you guys give it a round of review? |
@@ -383,15 +388,78 @@ FInterpreter CPUInterpreter() { | |||
return CreateInterpreter(Module(nullptr), CPUContext(), target); | |||
} | |||
|
|||
bool IsAtomic(const Expr& e) { | |||
return e.as<VarNode>() || e.as<OpNode>() || e.as<ConstructorNode>() || e.as<GlobalVarNode>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are constant nodes atomic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They arent: they are big.
I think it would be good to include some explanation as to the use of the creation time mechanism and why it's important for termination checking, as that was all very difficult for me to understand. More varied test cases (given how complicated the feature is) would be good too. |
@slyubomirsky it is not complicated at all! the high level idea is that the argument must be strictly decreasing in some order to be terminating. We choose the order to simply be the order it is created. This work for lots of the case, because for any adt, the outer node is newer then the inner node. So, as long as any of the argument is decreasing, it is good. To include the case where argument a decrease, argument b increase, then argument b increase, argument a decrease, we specify that decrease mean 'globally decrease' (etc: smaller then all seen time at that argument). |
@slyubomirsky I revisited the comment and couldnt figure out how to change it. Anything that is particularly confusing? |
I didn't mean that anything is confusing in itself, just that there should somewhere be a note explaining what the creation times are for and what it does. It took me a fair bit of reading and rereading and thinking to figure out how it worked and that is probably not good for future maintainability. |
@MarisaKirisame How do we prevent infinite loop of PE? One case I can think of is a function with 2 arguments, the series of created_time that can cause infinite loop is Do you think is this case possible and how do we prevent that? |
the lowest_bound is (1, 1), (0, 1), then (2, 1) is checked and found that it does not decrease any argument. I specifically design it to avoid this. I had no idea how to fix the comment though. Can you make some suggestion? |
@wweic I had add some test to make sure. They did pass. |
Thank you for expanding some of the comments |
@MarisaKirisame Got it. I missed that you compare timestamp with historical minimum. |
src/relay/pass/partial_eval.cc
Outdated
return recurse(); | ||
} else { | ||
// We check to see that at least one argument decrease | ||
// with respect to all previous invocation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe expand the comment here that the number of recursive inline calls is bounded by the first created time of all arguments(product of created times).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to comment how the number of recursive inline is bounded by created time.
/* We check to see that at least one argument decrease | ||
* with respect to all previous invocation. | ||
* The depth of the recursion is bounded by | ||
* the sum of the time of all argument at the first call. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's product in stead of sum?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is sum. everytime the sum must decrease by at least 1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes you are right. @MarisaKirisame
save save save upstream lint remove bad changes fix build save save please the ci god Update src/relay/pass/partial_eval.cc Co-Authored-By: Wei Chen <[email protected]> save fix test ci is ANGRY fix rebase problem fix rebase add test save save comment
save save save upstream lint remove bad changes fix build save save please the ci god Update src/relay/pass/partial_eval.cc Co-Authored-By: Wei Chen <[email protected]> save fix test ci is ANGRY fix rebase problem fix rebase add test save save comment
save save save upstream lint remove bad changes fix build save save please the ci god Update src/relay/pass/partial_eval.cc Co-Authored-By: Wei Chen <[email protected]> save fix test ci is ANGRY fix rebase problem fix rebase add test save save comment
@nhynes @wweic @icemelon9 @junrushao1994 @ZihengJiang @jroesch @tqchen can you guys review?