-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[MLIR] Refactor to create vectorization convOp precondition check #130181
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
Merged
jerryyin
merged 9 commits into
main
from
users/zyin/fix-vectorization-masking-convolution
Mar 17, 2025
Merged
Changes from 1 commit
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
a33b211
Blocking conv2d from vectorization pass
jerryyin 80474f7
Refactor Conv1DGenerator
jerryyin 00c3a33
Forward declare Conv1DGenerator for validaty
jerryyin 74a8986
Addressing review feedbacks
jerryyin 2ef5555
Peel away conv1dgen validator into precondition check
jerryyin 13f5183
Addressing review feedbacks
jerryyin 2b5d1dc
Amending comments of getConvOperationKind()
jerryyin a58b8da
Addressing review feedbacks
jerryyin f153804
Adding comment in conv precondition check
jerryyin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 couldn't find such Pass in-tree.
Uh oh!
There was an error while loading. Please reload this page.
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.
Apologize, this is an iree implementation detail and referenced pass is also from IREE. I shouldn't include such pass in upstream. Will remove.
Let me use this thread to discuss it. This diff code block is the high-level pre condition check around linalg op. Please let me know if you are referring to a different location.
Could you elaborate? Are you referring to explicitly invoke
inferConvolutionDims()? Then to make sure this is a regular 2d convolution, I'd check for a combination of:Reject if all of those satisfy. I have no problem to implement this, but just want to make sure we are on the same page.
Taking a step back, I don't have a lot of context about the history of the vectorization code around convolution. Since this PR is not intending to do a massive re-write, I'm attempting to be coherent with the existing code as much as possible.
One thing I've noticed and @hanhanW who righteously pointed out is that we can fail to build a
Conv1DGenerator, and still allow a function (like howvectorizeConvolution()construct and uses theConv1DGenerator) invoked on its member vectorization functions, which I find to be quite confusing. (If I'm to implement this from scratch, I'll probably use singleton + initialize compared to the approach (constructor +validmember variable). This way, a developer is required to invoke the initialize method and check validity of the class before invoking anything on it.)With this context, I find the most defensive approach is the one used from this PR right now:
With above reasoning added up, it just looks to me to be a better solution compared with inferring the convolution dimensions and reject a few corner cases (which can easily grow out-of-sync later).
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.
Similarly to Diego, I am suggesting to move the high level logic to
vectorizeOpPrecondition. Also, like other "pre-condition" hooks, it should not require a rewriter.In my naivety, I was hoping that checking e.g. the rank of the filter or the input would be sufficient. But clearly not - the input for non-channelled conv would be 1D, but for a channeled one would be 2D. So on and so forth. IMO, you can just create something like this:
This will be a bit verbose, but there's just too many convs and whatever we try will be ... verbose 🤷🏻
+1 to being coherent, thanks!
I was actually going to ask - do you have any plans regarding this code beyond this PR?
You should be able to simply add:
From what I can tell, that wouldn't break any tests and will make "validity" a strong pre-requisite.
There's been no new implementations in > 2 yrs. From what I can tell, we can safely assume that this will remain the case for the foreseeable future. So, I wouldn't worry about this.
That sounds good in theory, but in practice it means that we need an IR writer for the validation. "Validation"/"pre-conditioning" should not require a rewriter.
How about my suggestion with
isa?Uh oh!
There was an error while loading. Please reload this page.
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 really appreciate your thorough review comments which gives me a ton of useful information.
Thanks for asking! I don't have any further plans... Was only meant to unblock myself from a non-relevant crash that will fail downstream tests.
Agreed that I don't like to have a redundant dummy rewriter just for the validation too. In fact, I took a second look at all the instances of places where a
Conv1DGenerator's member function is invoked and find that all the places have access to a rewriter. The need for the rewriter really only comes from the base classStructuredGeneratorconstructor. Then, I'm also surprised to find that the base classStructuredGeneratordoesn't use the rewriter yet it unnecessarily stored this as the state to this class. A slightly more aggressive way is to get rid of the field from base class and move rewriter to base class on case by case manner. Then we'd have a clean way to construct it without requiring a rewriter. Sounds like a rabbit hole that I'd avoid from this PR :-pI'll adopt this. This is a cheap enough check that seems reasonable for pre-condition check. Although I'll refrain from being "complete" in this check because in reality, the
linalg.conv_2d_*andlinalg.conv3d_*is a really long list combined, with quantized, groupd and non-channel variants. I'm going to leave those other variants out and check for only simple conv2d and 3d cases.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 thought that it is moved to the
vectorizeOpPreconditionin the PR? The check is invectorizeLinalgOpPreconditionand the former one calls this function. Do you suggest creating a different function likevectorizeConvPrecondition, and we use it invectorizeOpPrecondition? It is okay to me because convolution really goes with a different path.RE verification issue: I totally agree that the verification should not depend on an IR rewriter. From what I can tell, we do not need it at all. The class needs it for
StructuredGenerator, but we dont need it in the verfication at all.llvm-project/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
Lines 3132 to 3179 in aa38754
The
validvariable is only used in assertions in few methods, e.g.,depthwiseConvandconv. I think it's mainly created for sanity check, while the new codes did not take it into account. Thus, we crashed in the other place.The code is quite old and the precondition was added later than the conv code. I think to make it in better structure, we can refactor the generator because everything is started from the generator. How about we have a static class method which returns true when the given operation is supported? That said, we move the above logic check to a static method (e.g.,
vectorizePrecondition) without initializing any variables.In the construction, I'd suggest doing simple things as much as possible. And we move the assertion out of the constructor. In the context, they are moved to an initializer method. Because I'd prefer avoiding a crash in the constructor, and we can expose the failure handling to external users. (I don't know what the style is in LLVM, but it is quite common in environments where exceptions are disallowed. See https://abseil.io/tips/42 for more details.)
Thus, it can be something like
Does it look better structured?