[water] Add ScaledMMAOp - #1136
Conversation
94d4061 to
993842a
Compare
439b4e1 to
fb7cc3b
Compare
Water Code Coverage |
There was a problem hiding this comment.
Pull request overview
This PR adds a ScaledMmaOp to the Wave dialect, supporting scaled matrix multiply-accumulate operations using microscaling floating point (MXFP) formats (e.g., FP4 with E8M0 scale factors). It includes the full stack: op definition, type/index inference, lowering to amdgpu.scaled_mfma, Python bindings, and the emitter path.
Changes:
- New
ScaledMmaOpin the Wave dialect with 5 operands (lhs, lhs_scale, rhs, rhs_scale, accumulator), full verification, type/index propagation, and elements-per-thread analysis - Lowering pattern from
wave.scaled_mmatoamdgpu.scaled_mfma, including scalar extraction for scale factors - Bug fix in
BitcastOp.scale_factorto useget_custom(self.arg).typeinstead ofself.arg.type
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| water/include/water/Dialect/Wave/IR/WaveOps.td | ODS definition of ScaledMmaOp with 5 inputs + kind attribute |
| water/lib/Dialect/Wave/IR/WaveOps.cpp | Verification, type/index propagation, EPT analysis, and new indexing expressions for F8F6F4 MMA kinds |
| water/lib/Dialect/Wave/Transforms/LoweringPatterns.cpp | Lowering pattern from ScaledMmaOp to amdgpu.ScaledMFMAOp |
| wave_lang/kernel/wave/mlir_converter/water_emitter.py | Python emitter support for ScaledMMA node → ScaledMmaOp |
| wave_lang/kernel/ops/wave_ops.py | _is_fp4 property, MMA_SCALE_FP4 in operand maps, BitcastOp bugfix |
| lit_tests/kernel/wave/mlir_converter.py | End-to-end test for MXFP4 scaled GEMM |
| water/test/Dialect/Wave/ops.mlir | Round-trip test for wave.scaled_mma |
| water/test/Dialect/Wave/python_bindings.py | Python binding tests for ScaledMmaOp |
| water/test/Dialect/Wave/propagate-elements-per-thread.mlir | EPT backward propagation test for scaled MMA |
| water/test/Dialect/Wave/lower-wave-to-mlir.mlir | Lowering tests for bitcast and scaled MMA |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
45f1e62 to
3c03902
Compare
73e0669 to
13aad36
Compare
3f873d5 to
ab7667a
Compare
1f183c1 to
69419ef
Compare
27c7483 to
47d782e
Compare
3b760b1 to
a6504eb
Compare
ftynse
left a comment
There was a problem hiding this comment.
Generally makes sense. My only concern is about isScaled and isFP4 that are not fully documented and the usage seems to be contradictory. I also see pywave has separate flags for LHS and RHS scaling, though I don't know if we have instructions allowing for that.
47d782e to
5c70720
Compare
53d5c77 to
44668c7
Compare
733ea10 to
52b3332
Compare
44668c7 to
aa69f48
Compare
b650686 to
1ffddf5
Compare
3fcd8c6 to
4e38dda
Compare
1ffddf5 to
16ce86c
Compare
4e38dda to
2500bfd
Compare
16ce86c to
5861fdf
Compare
6502ef3 to
9b34ced
Compare
809eb84 to
32708fb
Compare
9b34ced to
7c8b9a9
Compare
8fe578f to
c405f9f
Compare
7c8b9a9 to
3bde175
Compare
938a51a to
f906f20
Compare
| # Global reads promoted through shared memory. | ||
| # | ||
| # CHECK: wave.read %[[A]] | ||
| # CHECK: wave.write {{.*}} !wave.tensor<[@M, @K2] of i8, <shared>> | ||
| # CHECK: wave.read %[[A_SCALE]] | ||
| # CHECK: wave.write {{.*}} !wave.tensor<[@M, @K32] of i8, <shared>> | ||
| # CHECK: wave.read %[[B]] | ||
| # CHECK: wave.write {{.*}} !wave.tensor<[@N, @K2] of i8, <shared>> | ||
| # CHECK: wave.read %[[B_SCALE]] | ||
| # CHECK: wave.write {{.*}} !wave.tensor<[@N, @K32] of i8, <shared>> |
There was a problem hiding this comment.
Do we care about shared memory in this test? If not, I'd remove to reduce complexity.
There was a problem hiding this comment.
Yes, shared memory should be i8 and have the right (scaled) shape
| # CHECK: %[[SMMA0:.*]] = wave.scaled_mma {{.*}}, {{.*}}, {{.*}}, {{.*}}, %[[ACC]] | ||
| # CHECK-SAME: #wave.mma_kind<f32_16x16x128_f8f6f4> | ||
| # CHECK: %[[SMMA1:.*]] = wave.scaled_mma {{.*}}, {{.*}}, {{.*}}, {{.*}}, %[[SMMA0]] | ||
| # CHECK-SAME: #wave.mma_kind<f32_16x16x128_f8f6f4> | ||
| # CHECK: wave.yield %[[SMMA1]] : !wave.tensor<[@M, @N] of f32, <register>> | ||
| # CHECK-NEXT: } |
There was a problem hiding this comment.
Let's be systematic and either test variable names or not, but not be halfway with only accumulators.
f906f20 to
bd7eb3c
Compare
Implement ScaledMMA Op that operates on MXFP data types like MXFP4. Signed-off-by: Tim Gymnich <tim@gymni.ch>
bd7eb3c to
bac9618
Compare
Signed-off-by: Tim Gymnich <tim@gymni.ch>
60b7cf8 to
93feeec
Compare
Signed-off-by: Tim Gymnich <tim@gymni.ch>
|
happy CI is irrelevant |
fixes
scaled_mmaoperation and relevant mma kinds #924