Skip to content

[MoE] Keep the CK-Tile split-k route for SwiGLU MXFP4 callers that leave gate_up_interleave unset (MiniMax-M3 TP8 regression from #6478) - #6620

Merged
valarLip merged 2 commits into
mainfrom
zhiwei/fix-swiglu-mxfp4-untagged-layout
Oct 16, 2026
Merged

valarLip merged 2 commits into
mainfrom
zhiwei/fix-swiglu-mxfp4-untagged-layout

Conversation

@ZhiweiYan-96

@ZhiweiYan-96 ZhiweiYan-96 commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Since #6478 (88d7db6), ATOM's amd/MiniMax-M3-MXFP4 TP8 accuracy job generates garbage on every decode step and each GSM8K request runs to max_gen_toks=16384. The job then times out after ~35–54 min instead of passing in ~9 min. It has failed on every ATOM main run since aiter picked up 88d7db6: job 116798160693, 116822862840, 116835414847. The last pass (116770801850, aiter c118faf) scored GSM8K 0.9431. The other accuracy jobs in those runs still pass, apart from one unrelated 5-minute DeepSeek-R1-0528 MTP failure in one run.

Root cause

#6478 changed swiglu_mxfp4_bf16_cktile to require gate_up_interleave is False. Callers that never set w1.gate_up_interleave pass None; ATOM is one of them. With bf16/fp16 activations, these callers no longer take the CK-Tile split-k route with post_activation_layout="standard". They fall through to the "unshuffled weights" CK-Tile fallback (post_activation_layout="auto") instead. The failing CI server log shows SwiGLU MXFP4 with unshuffled weights not supported by CK2stages codegen; routing to CK-Tile (ROCM-25478); the passing log does not.

Only the TP8 shape reaches CK-Tile. A trace of get_2stage_cfgs inside the TP8 server shows the per-rank MoE call as model_dim 6144, inter_dim=512, intermediate_pad=0, E=129, top-5. Every decode step (M ≤ 256, bf16 activations) goes to CK-Tile. At TP4 the call has inter_dim=768, and FlyDSL handles every M, so a TP4 run on 88d7db6 stays healthy (GSM8K 64-sample 0.9375).

Route chosen for the TP8 decode calls, recorded by the same server-side trace:

aiter route post_activation_layout bias
c118faf (before #6478) CK-Tile split-k standard True/True
88d7db6 unshuffled-weights fallback → CK-Tile auto (M ≤ 8) / unset (M ≥ 16) False/False
88d7db6 + this PR CK-Tile split-k standard False/False

Fix

Treat an untagged layout (None) with bf16/fp16 activations the way swiglu_mxfp4_bf16_cktile did before #6478. Tagged callers (True / False) take exactly the same route as on main.

Validation

All runs are on MI355X (gfx950).

End to end: ATOM main (ffd113b), MiniMax-M3-MXFP4, TP8, CI server flags and env. GSM8K 5-shot chat uses --limit 64 and max_gen_toks=4096. The direct probe sends 8 GSM8K questions at temperature=0.

aiter GSM8K (64) probe: requests ending on length probe completion tokens
88d7db6 0.0000 8 / 8 4096 each (garbage text)
88d7db6 + this PR 0.9219 0 / 8 105–276, mean 195

Kernel: op_tests/test_moe_2stage.py::test_fmoe on the traced TP8 call shape. The shape is 6144 / 512 / pad 0 / E=129 / top-5, SwiGLU limit 7, no bias, preshuffled MXFP4 weights, AQDType=fp4x2. Every aiter build runs the same harness, the 88d7db6 copy. The table gives logits_diff = 1 − cosine similarity to the torch reference:

tokens 88d7db6 88d7db6 + this PR c118faf
1 0.998 0.0810 0.0806
8 0.980 0.0751 0.0751
32 0.981 0.0722 0.0722
128 0.974 0.0737 0.0737

With this PR the error goes back to the c118faf baseline. The ~0.07 baseline is the pre-existing value #6478 already noted for this shape.

Tests. The new test_swiglu_mxfp4_untagged_layout_dispatch asserts the CK-Tile split-k route with post_activation_layout="standard" for the traced TP8 call. It passes with this PR and fails on main (got 'auto'). The existing test_swiglu_mxfp4_nonsplit_nobias_dispatch still passes. black and ruff (0.16.0) are clean.

…ave gate_up_interleave unset

#6478 made the CK-Tile split-k route (swiglu_mxfp4_bf16_cktile) require
w1.gate_up_interleave is False. Callers that never set the attribute pass None,
and with bf16/fp16 activations they now fall through to the "unshuffled weights"
CK-Tile fallback, which runs with post_activation_layout="auto" instead of
"standard". ATOM's MiniMax-M3-MXFP4 at TP8 (per-rank inter_dim 384 padded to 512)
hits exactly this on every decode step: the MoE output is uncorrelated with the
reference and generation runs to max tokens.

Treat an untagged layout (None) with bf16/fp16 activations as before #6478.
Tagged callers (True/False) are unchanged. Add a dispatch regression test for the
untagged case on the MiniMax-M3 TP8 shape.
@ZhiweiYan-96
ZhiweiYan-96 requested review from a team and a balanced review from Copilot October 16, 2026 10:00

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

Copy link
Copy Markdown
Contributor

🏷️ CI Guide

Runs automatically on every PR:

  • ✅ Pre-checks (submodule verification, code formatting)
  • ✅ Aiter op tests (gfx942 + gfx950)
  • ✅ Triton tests on MI35X (only when aiter/ops/triton/** or related paths are changed)

Extended tests (opt-in via labels):

Label Tests
ci:gfx1250-ffm-triton Run the five-shard gfx1250 FFM Triton test suite
ci:triton-300x Run an additional Triton test job on MI300X in PRs (added automatically when gfx942 configs change); main branch always runs both MI35X and MI300X
ci:triton-355 Run the full Triton test suite on MI35X, not only the tests the change affects
ci:windows Windows JIT op smoke test on the gfx1201 ROCm runner
ci:multi-gpu Aiter multi-GPU tests on the 8-GPU runner
ci:sglang SGLang integration tests: DeepSeek-R1-MXFP4 accuracy, Qwen 3.5 accuracy
ci:atom ATOM benchmark: DeepSeek-R1-0528, GPT-OSS-120B
ci:atom_full ATOM accuracy suite for PR and main models from ATOM models_accuracy.json
ci:vllm vLLM benchmark: DeepSeek-V4-Pro, MiniMax-M3-MXFP4
ci:all All standard extended tests (excludes ci:atom_full)

Only add ci:atom_full for FlyDSL or Triton upgrades.
Add labels via the sidebar or gh pr edit 6620 --add-label <label>

One backend per PR:
A PR changes one kernel backend: [Triton/Gluon] (Triton and Gluon count as one), [HIP], [ASM], [CK], [OPUS] or [FlyDSL]. If the title ends up with two backend tags, split the PR -- as stacked pull requests when one part cannot merge without the other.

PR title tags & labels:
Component tags ([Triton/Gluon], [HIP], [CK], [ASM], ...) are added to the PR title and as PR labels automatically from the changed files and re-synced on every push — change-type tags like [fix]/[Perf], op tags like [MLA], and human labels (ci:*) are left untouched. Add the no-auto-title label to stop the title rewrites; labels stay in sync either way.

…agged-layout test

A server-side trace of get_2stage_cfgs shows inter_dim=512 with intermediate_pad=0
for this call, not intermediate_pad=128.
Copilot AI balanced review requested due to automatic review settings October 16, 2026 12:47

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@valarLip
valarLip merged commit ea3d22a into main Oct 16, 2026
@valarLip
valarLip deleted the zhiwei/fix-swiglu-mxfp4-untagged-layout branch October 16, 2026 12:51
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.

3 participants