-
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][Pass] Fix lambda lift pass for recursive call #4432
Conversation
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.
LGTM. @jroesch PTAL
Does this work for non-immediate recursion? |
@MarisaKirisame No, we couldn't support non-immediate recursion. In this case, you need to support mutual recursion, which is still a pending PR(#2648). |
@MarisaKirisame I was wondering what the proper way is to do lambda lifting, where lambda could be returned or passed into a new function? |
@icemelon9 the program above do not rely on the mutual recursion feature. |
@junrushao1994 A global function returning that closure can be used to implement returning closure. (In this case, the old lambda lifting behavior is an optimization that do not return the closure, but call it directly). |
@MarisaKirisame Thank you for your reply! I am very ignorant in this field, and super interested in learning more. Would you mind suggesting better ideas if you have time? Definition(?). I was thinking, lambda lifting should be a pass that eliminates free variables and lifting lambdas to global scope. Like what is described in Wikipedia. Simplest case. If a lambda can be converted is only used inside relay.call, then it is safe to lift it to a tuple (global_var_lifted, captured_0, captured_1, ...). Mutual recursion works in this case as well. More complicated case. However, in the general case, when lambda is first-class supported (like relay), it could be hard to lift them, because when adjusting call sites, type mismatch could happen (consider conditionally bind 2 lambdas to a variable, which might capture different things). Your suggestion. As you suggested, in this case, make a "global function returning that closure can be used to implement returning closure." This is one of the solution that I was thinking before. It works, but I am not sure if it really helps (because closure still exists). What Wikipedia says. In the section "algorithm", it says:
Why I ask this If we are able to eliminate those lambdas, to "some data structure", then we are able to do autodiff without reference... |
@junrushao1994 No need to say that! DL compiler require many expertise and we are all ignorant in different things. How to do autodiff of lambda with minimal amount of reference?The method of turning lambdas into datastructure is well known and it is called defunctionalization. Basically, it try to make a new datatype, Func, where every single constructor is a "lambda" in the AST, and the constructor take in the closure number. For example, suppose the AST contain the following lambda, all taking two int and returning int we can then turn some adt containing reference into reference of pure adt. After that we can then do store passing style to that single reference. But I do not think that we can in general remove it (I had tried like 10 times). Off a side note, why are you so eager to remove reference? I need to write paper and I think this is a good paper story. I will talk about lambda lifting below, but I think we should not mix up lambda lifting with defunctionalization. |
For lambda lifting, note that our main use of ll right now is to massage the code into a form suitable for VM Compiler. We can make the VM Compiler appreciate lambda-lifted closure returning code. |
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.
LGTM
Thanks @icemelon9 . This is now merged. |
* Fix lambda lift * clean up * lint * fix * remove unused import
* Fix lambda lift * clean up * lint * fix * remove unused import
* Fix lambda lift * clean up * lint * fix * remove unused import
* Fix lambda lift * clean up * lint * fix * remove unused import
Thanks for contributing to TVM! Please refer to guideline https://docs.tvm.ai/contribute/ for useful information and tips. After the pull request is submitted, please request code reviews from Reviewers by @ them in the pull request thread.
cc @jroesch @zhiics @wweic