-
Notifications
You must be signed in to change notification settings - Fork 3.7k
[TIR] Avoid all-pairs comparison in subexpr elimination #11423
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
Conversation
Subexpression elimination used a comparison of each subexpression to every other subexpression to determine which to eliminate. This resulted in an O(N^2) algorithm that was slow when there were many LetStmts. Instead we now hash each subexpression and compare the hashes. We reuse structual hashing without remapping free variables to uniquely determine each subexpression.
AndrewZhaoLuo
left a comment
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.
Thanks for doing this, I have noticed this pass is a little slow when conducting some synthetic tests with lots of subexpressions.
|
@AndrewZhaoLuo comments addressed |
AndrewZhaoLuo
left a comment
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
|
Hi, Thank you for your interest in improving the pass! 1) The whole need for this function is due to having collected syntactical entities (using an efficient structure for that, the ComputationTable, where it's fast to retrieve an element (in constant time), as it's a hashtable), which latter of course needs to be transformed into a collection (a vector), where equivalent terms (like x+y and y+x) are merged together (and their counters added), which I then call semantical entities. This notion of being semantically equivalent could be anything, like identifying terms modulo associativity [(x+y)+z with x+(y+z)], modulo commutatitvity [x+y with y+x], or anything else, with any equivalence relation. It's completely customizable by just changing the Sure, at the moment, this function 2) If the pass is really taking too long for many people, I could try to help to improve it, if that's needed. There will necessary be a limit in what we can gain at compile time, as improving the runtime speed (or creating opportunities for it, which CSE is doing) often has a price to pay at compile time. But we can see what we can do, for sure. What do you think? |
|
Thanks for helping to clarify things @FranckQC! I think I'm a little confused still. Regarding 1), you are saying that right now Even if we switch Regarding 2), I didn't realize |
|
@FranckQC thanks for elucidating the intention of the original design. I see why for an arbitrary semantic computation functions you may need to have N^2 comparisons. Is it possible to relax the number of comparisons by using a canonical form. E.g. Regardless, this has O(N^2) for little benefit (as we do equality only) at the moment so I propose to comment out the original impl. and replace it with a O(N) fast one / no op, and add a suitable comment. |
AndrewZhaoLuo
left a comment
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.
Turning off the merge approval until we hash this out.
|
Hi everyone,
Hum, no, I wouldn't say it does nothing. It still transforms a hastable into a vector. How it does so depends on the
As a use case of this kind of thing: I think I should be able to address the issue without removing completely the possibility to have more interesting comparisons in the future. Thanks. |
|
@FranckQC because this currently is causing issues, how about we remove the code for now. When you figure out a solution we can add the code back in. |
|
If that's solved by tomorrow, would that work for you? |
|
Sure, that is probably fine. Thank you for the quick turnaround. |
|
I think the main issue I have O(N^2) runtime on a default pass. We can do linear time if we plan things well, e.g. have syntactic canonical forms. Haven't dug too deeply, but if this normalization stuff does something like this I will be cool |
|
@FranckQC any update on a solution? |
|
Just starting to work on it now. Was busy with other things earlier today. |
|
I don't think @AndrewZhaoLuo or I will be back to review this until Tuesday so don't feel rushed. |
|
Just a small update to let you know that I have a patch almost ready for that. Just testing it now (both functionally and performance-wise) to make sure everything is ok. |
|
@FranckQC any update? |
|
Sorry, it's currently being reviewed in our repo downstream. I hope to make the PR here this afternoon! |
|
Hi, The PR is ready here : #11574 Thanks! |
|
Thanks @FranckQC. |
Subexpression elimination used a comparison of each subexpression to every other subexpression to determine which to eliminate. This resulted in an O(N^2) algorithm that was slow when there were many LetStmts. Instead we now hash each subexpression and compare the hashes. We reuse structual hashing without remapping free variables to uniquely
determine each subexpression.
@masahi @FranckQC