Skip to content

[MiniMax-M3.1] Run the DSpark draft's MXFP8 linears on AITER's preshuffled GEMM - #2876

Open
zhuyuhua-v wants to merge 1 commit into
mainfrom
yuhzhu/mxfp8-1x32-preshuffle
Open

zhuyuhua-v wants to merge 1 commit into
mainfrom
yuhzhu/mxfp8-1x32-preshuffle

Conversation

@zhuyuhua-v

@zhuyuhua-v zhuyuhua-v commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

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 sets needs_preshuffled_weight on each layer's qkv_proj, o_proj, gate_up_proj and down_proj.
  • atom/model_ops/linear.py: weight_is_stored_preshuffled preshuffles a native 1x32 FP8 weight only when its module asks, on gfx950, under the existing ATOM_GROUP32_WEIGHT_PRESHUFFLE switch. 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:

rows before (Triton) this PR speedup
8 106.5 us 38.7 us 2.75x
64 133.6 us 50.3 us 2.66x
256 195.7 us 87.5 us 2.24x
512 319.4 us 121.2 us 2.64x

End to end: MiniMax-M3.1-Flash, TP4, AgentX c32, 3600 s, one run each, on the ganyi/m31-mono-fp4-pr stack (#2812), with the same draft weights preshuffled.

before this PR
P90 interactivity 140.6 144.9
P50 interactivity 213.7 220.8
total tok/s/GPU 57,943 57,943

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:
    • the 1x32 truth table;
    • load-vs-sync parity on the native group32 branch.
  • 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.
  • 93 passed on MI355X with aiter 1053d8d18. Both files skip on CI's unit runner (no aiter / GPU).

Notes

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

🏷️ CI Guide

Runs automatically on every eligible PR before approval:

  • ✅ Pre Checkin: Black, Ruff, catalog schema validation, non-GPU unit tests

Heavy model tests:

  • ✅ Run after the PR is approved and Pre Checkin passes
  • ✅ Run immediately when an approval review is submitted
  • ✅ Can be requested before approval with labels
Label Tests
ci:full Run all heavy PR model tests: native ATOM, vLLM, and SGLang
ci:atom Run native ATOM model accuracy tests
ci:vllm Run ATOM vLLM OOT model accuracy tests
ci:sglang Run ATOM SGLang model accuracy tests

Heavy jobs are skipped when the PR is not approved and no matching ci:* label is present.
Add labels via the sidebar or gh pr edit 2876 --add-label <label>

@zhuyuhua-v
zhuyuhua-v force-pushed the yuhzhu/mxfp8-1x32-preshuffle branch from 63c4bc1 to 1d2fc46 Compare November 2, 2026 07:19
@zhuyuhua-v zhuyuhua-v changed the title [MiniMax-M3.1] Preshuffle native MXFP8 (1x32) weights for AITER's preshuffled GEMM (opt-in) [MiniMax-M3.1] Preshuffle native MXFP8 (1x32) weights on gfx950 for AITER's group32 GEMM Nov 2, 2026
@zhuyuhua-v
zhuyuhua-v marked this pull request as ready for review November 2, 2026 07:39
Copilot AI balanced review requested due to automatic review settings November 2, 2026 07:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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_PRESHUFFLE switch.
  • 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

Comment thread atom/model_ops/linear.py Resolved

@valar-cop valar-cop left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some changes needed..

ci green.

Comment thread atom/model_ops/linear.py Resolved
@zufayu
zufayu requested a review from HaonanWang98 November 3, 2026 01:13
Copilot AI balanced review requested due to automatic review settings November 4, 2026 07:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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

Comment thread atom/model_ops/linear.py Resolved

@valar-cop valar-cop left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some changes needed..

ci green.

Comment thread atom/model_ops/linear.py Resolved
@zhuyuhua-v
zhuyuhua-v force-pushed the yuhzhu/mxfp8-1x32-preshuffle branch from ab92685 to 2573f8f Compare November 4, 2026 11:36
Copilot AI balanced review requested due to automatic review settings November 4, 2026 11:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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

Comment thread atom/model_ops/linear.py Resolved
Comment thread atom/model_ops/linear.py Resolved
…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.
@zhuyuhua-v
zhuyuhua-v force-pushed the yuhzhu/mxfp8-1x32-preshuffle branch from 2573f8f to a8d9ae8 Compare November 4, 2026 12:08
Copilot AI balanced review requested due to automatic review settings November 4, 2026 12:08
@zhuyuhua-v zhuyuhua-v changed the title [MiniMax-M3.1] Preshuffle native MXFP8 (1x32) weights on gfx950 for AITER's group32 GEMM [MiniMax-M3.1] Run the DSpark draft's MXFP8 linears on AITER's preshuffled GEMM Nov 4, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 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 open issue
1 resolved since last review

Review effort: Balanced

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants