Repository navigation
[MiniMax-M3.1] Run the DSpark draft's MXFP8 linears on AITER's preshuffled GEMM - #2876
zhuyuhua-v wants to merge 1 commit into
Conversation
🏷️ CI GuideRuns automatically on every eligible PR before approval:
Heavy model tests:
|
63c4bc1 to
1d2fc46
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The default gfx950 path selects preshuffling for supported native weight shapes that the shuffle cannot tile, causing weight loading to fail unless the shared load/sync decision checks shape compatibility.
1 open issue
What changed in this PR
This PR extends ATOM’s native FP8 preshuffling to 1x32 MXFP8 weights on gfx950, allowing MiniMax-M3.1 DSpark draft linears and other eligible checkpoints to use AITER’s preshuffled group32 GEMM.
Changes:
- Enables native 1x32 FP8 preshuffling under the existing
ATOM_GROUP32_WEIGHT_PRESHUFFLEswitch. - Adds eligibility, dispatch, and GPU bit-exact comparison tests.
- Documents the switch’s expanded scope.
| File | Description |
|---|---|
tests/test_weight_sync_shuffle_layout.py |
Tests architecture and switch eligibility, plus unchanged FP4 behavior. |
tests/model_ops/test_blockscale_dispatch.py |
Tests AITER dispatch and bit-exact results against row-major GEMM. |
docs/environment_variables.md |
Documents native 1x32 MXFP8 preshuffling. |
atom/model_ops/linear.py |
Extends the shared load/sync shuffle policy to native 1x32 FP8 weights. |
Review effort: Balanced
There was a problem hiding this comment.
🟡 Changes recommended
The default-enabled gfx950 guard admits unsupported weight shapes that fail on the first forward pass because shuffle compatibility does not ensure AITER kernel support.
1 open issue
1 resolved since last review
Review effort: Balanced
ab92685 to
2573f8f
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The default-on gfx950 path can fail weight loading when optional dependencies are missing and breaks previously supported FP32 output for preshuffled native 1x32 weights.
2 open issues
1 resolved since last review
Review effort: Balanced
…ffled GEMM The MiniMax-M3.1 DSpark draft keeps its linears as shipped: MXFP8, FP8 E4M3 with a 1x32 E8M0 scale, read as native group32 weights. Row-major, they ran on the Triton group32 GEMM (gemm_afp8wfp8, default config). The draft now asks for its qkv / o / gate_up / down weights to be (16, 16)-preshuffled (needs_preshuffled_weight), and weight_is_stored_preshuffled honours that for a 1x32 weight on gfx950 under ATOM_GROUP32_WEIGHT_PRESHUFFLE. native_quant_linear's existing AITER call then runs them on FlyDSL's MXFP8 bmm, whose MiniMax-M3 1x32 tuned rows (ROCm/aiter#6060) cover these shapes. Only the layout changes: the output is bit-identical. Every other 1x32 weight, and every other arch, stays row-major. Tests: the 1x32 truth table, load-vs-sync parity on the native group32 branch, and a gfx950 bit-exact check at the draft's TP4 shapes.
2573f8f to
a8d9ae8
Compare
There was a problem hiding this comment.
🔵 Needs a closer look
The snapshot lacks the claimed guards and boundary tests, while the AITER #6060-dependent gfx950 behavior remains unverified because the affected tests skip on CPU and GPU validation was unavailable.
1 resolved since last review
Review effort: Balanced


Summary
The MiniMax-M3.1 DSpark draft keeps its linears as shipped: MXFP8 (FP8 E4M3, one E8M0 scale per 32). Until now they were held row-major and ran on the Triton group32 GEMM. This PR (16, 16)-preshuffles them at load, so
native_quant_linear's existing AITER call runs them on FlyDSL's MXFP8 bmm. AITER already ships MiniMax-M3 1x32 tuned rows for these shapes (ROCm/aiter#6060).Only the layout changes; the output is bit-identical. Only the draft is affected: every other 1x32 weight, and every other arch, stays row-major.
Change
atom/models/minimax_m3/dspark.py: an MXFP8 draft setsneeds_preshuffled_weighton each layer'sqkv_proj,o_proj,gate_up_projanddown_proj.atom/model_ops/linear.py:weight_is_stored_preshuffledpreshuffles a native 1x32 FP8 weight only when its module asks, on gfx950, under the existingATOM_GROUP32_WEIGHT_PRESHUFFLEswitch. The load and the weight sync both go through it.Performance
Draft linears, TP4 per-rank shapes, one MI355X. Timings are per layer (2 x qkv + o + gate_up + down), with activation quantization included:
End to end: MiniMax-M3.1-Flash, TP4, AgentX c32, 3600 s, one run each, on the
ganyi/m31-mono-fp4-prstack (#2812), with the same draft weights preshuffled.gsm8k (5-shot, 1319 samples, real DSpark acceptance): strict-match 0.9666, against 0.9621 / 0.9629 before.
Tests
tests/test_weight_sync_shuffle_layout.py:tests/model_ops/test_blockscale_dispatch.py: on gfx950, a bit-exact check of the preshuffled 1x32 GEMM against the row-major path at the draft's shapes.1053d8d18. Both files skip on CI's unit runner (no aiter / GPU).Notes
mainsince 2026-10-27).ATOM_GROUP32_WEIGHT_PRESHUFFLE=0restores the row-major path.🤖 Generated with Claude Code