Repository navigation
[AMD] Fix wrong MoE output at small batch with aiter fp8 block-scale (split-K with one K tile per split) - #43354
Open
ntgiang71096 wants to merge 1 commit into
Conversation
aiter's ck_moe_stage1 accumulates split-K partials into a torch.empty fp32 buffer that CK only zeroes when every split owns at least two K tiles (KBatch = K // (splitk * 256) > 1). For small M the default heuristic picks a split with KBatch == 1 (e.g. Qwen3.6-35B-A3B-FP8 at TP1, M=1), so the MoE output is garbage: single-request decode emits "!!!!", 1-token radix extends are wrong, and the MTP draft is corrupted. aiter guarded this in sgl-project#3997 and lost the guard in sgl-project#4394 (ROCm/aiter#4032). Wrap ck_moe_stage1 once from AiterRunnerCore and lower such splits to the largest count that keeps >= 2 K tiles per split (0 if none). All other calls are passed through unchanged.
ntgiang71096
requested review from
BBuf,
Edwardf0t1,
Fridge003,
HaiShaw,
Ying1123,
ch-wan,
ispobock and
merrymercy
as code owners
October 9, 2026 10:17
Contributor
Author
|
@hnyls2002 Following up on your note in #29633: the M=1 issue does still reproduce on the unified-cache tree. The root cause turned out to be in aiter's split-K path rather than the radix cache: Could you take a look and run |
This was referenced Oct 10, 2026
This branch has not been deployed
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Motivation
What users see. On the ROCm images
lmsysorg/sglang-rocmv0.5.20 and v0.5.21, Qwen3.6-35B-A3B-FP8 at TP1 produces garbage when only one request is running: a few correct tokens, then!!!!. The same bug also causes two other problems:extra_buffer);Reproduce (MI350X,
lmsysorg/sglang-rocm:v0.5.21-rocm724-mi35x-20261002;SGLANG_USE_AITER=1is the image default):Cause. For very small batches, aiter splits the stage1 MoE GEMM along K and adds the partial results into one buffer. For Qwen3.6-35B at M=1, K=2048 is split 8 ways (256 each), so every split owns exactly one K tile. In that configuration CK skips zeroing the buffer, but the splits still accumulate into it. The buffer comes from
torch.empty, so the result lands on stale memory.aiter guarded this case in ROCm/aiter#3997, but ROCm/aiter#4394 dropped the guard. It is tracked in ROCm/aiter#4032. The v0.5.16 image (aiter
d9e5ef7) still has the guard.Modifications
At
AiterRunnerCoreinit, sglang wrapsaiter.fused_moe.ck_moe_stage1once:Why in sglang, and why it is safe:
apply_aiter_small_moe_sort_patch, MoE: small-batch sorting path with fused mxfp8 quantisation #36559).TODOdrops it once the minimum supported aiter carries the guard again. If aiter fixes it first, the wrapper is harmless.AITER_KSPLIT=1: that disables split-K for every call and slows small-batch decode.smallm_moe_gfx950kernel and never reachck_moe_stage1. This change covers the remaining shapes, and gfx942.Accuracy Tests
Qwen3.6-35B-A3B-FP8, TP1, MI350X,
v0.5.21-rocm724-mi35x-20261002,--attention-backend triton --mamba-radix-cache-strategy extra_buffer. Serving logprobs are compared against logprobs recomputed by a clean prefill, following sglang'skl_test_utils.Details: equivalence on unchanged paths, kernel-level check, affected models and TP
Equivalence on unchanged paths
Kernel level
fused_moeis compared against an fp32 reference, including with the caching allocator pre-filled with NaN.Affected models and TP (MI350X/MI355X, default heuristic):
Speed Tests and Profiling
Qwen3.6-35B-A3B-FP8, TP1, MI350X, single request, same image and flags as above:
GPU time per MoE call at M=1
Tests
Added
test/registered/amd/test_aiter_moe_splitk_kbatch_guard.py:fused_moeat M=1/2/4/8 and compares against an fp32 reference.Checklist
CI States
Latest PR Test (Base): ❌ Run #37916671528
Latest PR Test (Extra): ❌ Run #37916671150
Latest PR Test (AMD ROCm 10): ❌ Run #37916671514