Repository navigation
[AMD] gfx950 small-batch MoE: expert-count gate for the small sort and FP8 block-scale small-M kernel - #41982
Merged
HaiShaw merged 13 commits intoOct 9, 2026
Conversation
…re it beats aiter
Collaborator
…r TP4/TP8 Co-authored-by: Cursor <cursoragent@cursor.com>
chuyeh
marked this pull request as ready for review
October 1, 2026 12:49
chuyeh
requested review from
BBuf,
DarkSharpness,
Edwardf0t1,
Fridge003,
HaiShaw,
HydraQYH,
Ying1123,
celve,
ch-wan,
ispobock,
merrymercy and
yuan-luo
as code owners
October 1, 2026 12:49
…I35x Require both FP8 weights to be shuffled and both block scales to be contiguous, since the kernel indexes them as raw arrays. Move the gfx950-only tests to the MI35x suite so they no longer skip on MI300, and set est_time from measured runs.
4 of 5 tasks
…56 experts Measured on MI355X: past the compact range the distributed sort beats aiter at MiniMax-M3's E=129 but loses at Qwen3.5's E=513, with or without the fused mxfp8 quant (TP8 FP8 bs 4: 1.7 ms per cycle). Gate on num_experts instead of deleting the kernel, and test the distributed path at MiniMax-M3 shapes.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as duplicate.
This comment was marked as duplicate.
Collaborator
|
base-c-test-8-gpu-b300 / base-c-test-8-gpu-b300 (0) server is off. Ref: #42463 |
yichiche
approved these changes
Oct 6, 2026
yichiche
left a comment
Collaborator
There was a problem hiding this comment.
- Affected Scope: NVIDIA behavior is unchanged. It does not run AiterRunner or the small-sort wrapper.
- AMD Guard: The expert cutoff is the AITER small-sort wrapper, with no gfx check. The FP8 kernel runs only on gfx950, and only from AiterRunner.run.
- Unit Test Quality: The tests use unittest, check real results, and stay under 500s. Coverage is mixed at sorting_impl_wrapper, which does not fail this row.
- Accuracy evidence: The PR body reports an accuracy result.
- Performance evidence: The PR body reports a performance result.
- Flags: No new environment variable.
LGTM.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
2 similar comments
This comment was marked as outdated.
This comment was marked as outdated.
Contributor
Author
|
/rerun-failed-ci |
HaiShaw
approved these changes
Oct 9, 2026
4 of 5 tasks
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
Qwen3.5-397B-A17B-FP8 on MI355X is slower than B200 at low concurrency in the AgentX benchmark (InferenceX PR #3602). One factor is the MoE sort from #36559: past its compact range, its distributed kernel scans every 64-expert chunk per pair, so with Qwen3.5's 513 experts it is slower than AITER's sort for mid-size decode batches (6 to 23 tokens). At TP8 with 16 verify tokens, going back to AITER's sort saves 1.7 ms per decode cycle.
This PR does two things:
With this PR, the interactivity improves by about 20% at concurrency 1 and 4.
Modifications
moe_sorting_small.py: past the compact kernel's range (min(64, 2 * block_size)(token, expert) pairs), the distributed kernel only runs for up to 256 experts; above that, the sort and the fused MXFP8 quantization go back to AITER (+13 / -3).smallm_moe.hip:p1_body/p2_bodytake anF8template flag. Shuffled FP8 weights have the same byte layout as fp4x2, so the load path is shared. e4m3 is converted to bf16 at scale 1.0 and each 128x128 block's fp32 scale is applied to the partial sum (cvt_scalef32_pk_bf16_fp8only applies the scale's exponent). New kernels cover TP4 (intermediate 256) and TP8 (intermediate 128); the MXFP4 kernels are unchanged.smallm_moe_gfx950/__init__.py: takes the FP8 path for shuffledfloat8_e4m3fnw13/w2with contiguous fp32 block scales, up to 20 tokens at TP4 and 48 at TP8.SGLANG_ROCM_SMALLM_MOE=0still turns the kernel off.moe_runner/aiter.py: passesw13_scale/w2_scaletosmallm_moe_supported(+2 lines).TestSmallMMoeFp8Gfx950checks both shapes against a dequantized reference at 1 / 3 / 8 tokens and the cap, and that cap+1, per-channel or non-contiguous scales, and unshuffled weights fall back. Newtest_moe_sorting_small.pycompares the sort and the fused MXFP8 quant with AITER on the compact path (Qwen3.5 shape) and the distributed path (MiniMax-M3 shape, 13 to 51 tokens), and checks the fallback at 513 experts.Accuracy Tests
All runs use image
rocm/sgl-dev:v0.5.20-rocm720-mi35x-20260927(same image aslmsysorg/sglang-rocmwith that tag), InferenceX recipe flags, GSM8K 1319 questions.Qwen/Qwen3.5-397B-A17B-FP8sglang.test.few_shot_gsm8kamd/Qwen3.5-397B-A17B-MXFP4-AttnFP8-V2(sort change)The FP8 kernel's rel L2 against the dequantized reference is at most 7.4e-4 over 5 seeds in the unit test. The sort output matches AITER's layout in every path, so the sort change only affects speed.
Benchmarking and Profiling
Kernel microbenchmarks
MI355X, one GPU, CUDA graph replay, Qwen3.5-397B shapes (
E=513, 11 slots per token, hidden 4096).FP8 MoE layer, AITER (
per_128x128) vs the FP8 small-M kernel, in µs:TP8 caps, 60 layers rotated so the weights are not cache resident:
AITER moves to a slower configuration from 36 tokens, so the TP8 cap is 48 rather than 32.
MoE sort past the compact range, in µs, block size as AITER picks it. MXFP rows include the MXFP8 quant in both arms (AITER runs it as a second launch). Up to the compact range the sort is unchanged, and the FP8 small-M path does not use the sort:
E=129, top-4 + shared, sort + quant)AITER picks block size 32 for the MXFP shapes and mostly 16 for Qwen3.5 FP8, where the compact kernel covers only 1 to 2 tokens.
AgentX benchmark
Setup:
Qwen/Qwen3.5-397B-A17B-FP8with the InferenceX recipeqwen3.5-fp8-mi355x-sglang-agentic, imagerocm/sgl-dev:v0.5.20-rocm720-mi35x-20260927.aiperf profile --scenario inferencex-agentx-mvponsemianalysis_cc_traces_weka_062126_256k, 3600 s per run.Baseline is the image as shipped: AITER's FP8 MoE with #36559's sort (
SGLANG_ROCM_SMALLM_MOE=0). With this PR, every decode batch at these concurrencies runs the FP8 small-M kernel and skips the sort, so the gain here comes from the kernel.Concurrency 1:
Concurrency 4:
Each EAGLE verify pass sends 4 tokens per running request through the MoE. At TP4 the kernel therefore covers running batches of 5 or fewer, which is concurrency 4 and below here; concurrency 8 and up mostly uses AITER.
Decode step time
Time for one EAGLE draft + verify cycle at a fixed batch size, same server flags and simulated acceptance.
TP4, image as shipped vs this PR, mean of two runs with the GPU sets swapped, in ms:
TP8, this PR with
SGLANG_ROCM_SMALLM_MOE=1vs0(kernel vs AITER's MoE and sort), two runs per arm in ABBA order. Run-to-run noise is up to 0.23 ms:With the kernel off at batch size 4 (176 pairs), #36559's sort takes 33.00 ms per cycle and this PR's 31.28 ms, the 1.7 ms in Motivation.
Checklist
CI States
Latest PR Test (Base): ✅ Run #37556056254
Latest PR Test (Extra): ❌ Run #37556056047
Latest PR Test (AMD ROCm 10): ❌ Run #37556056190