Repository navigation
[Perf][MiniMax-M3] Sequence parallelism and GEMM-RS for TP + MegaMoE - #64659
Merged
Merged
Conversation
Under TP > 1 with expert parallelism and the DeepGEMM MegaMoE backend (PP1), keep the decoder's residual stream sharded by token across the TP group: attention and the dense MLPs all-gather their input and reduce-scatter their output, MegaMoE consumes the local shard directly, and the output plus EAGLE3/DSpark aux hidden states are all-gathered once at the end. This replaces the two all-reduces per layer. With VLLM_ENABLE_GEMM_RS=1, o_proj and the dense down_proj fuse their GEMM with the reduce-scatter above 1024 tokens. GEMM-RS now also accepts a pre-quantized MXFP8 QuantizedActivation, which the fused dense GEMM1 emits. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Thien Tran <gau.nernst@yahoo.com.sg>
SP is covered by the existing GEMM-RS kernel test and end-to-end validation; the removed tests only checked configuration and used stand-in modules. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Thien Tran <gau.nernst@yahoo.com.sg>
With max_num_batched_tokens below the 1024-token GEMM-RS threshold the kernel can never run, and its workspace init asserts max_M >= 128. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Thien Tran <gau.nernst@yahoo.com.sg>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Thien Tran <gau.nernst@yahoo.com.sg>
gau-nernst
marked this pull request as ready for review
October 30, 2026 07:01
gau-nernst
requested review from
WoosukKwon,
mgoin and
tlrmchlsmth
as code owners
October 30, 2026 07:01
Contributor
Author
|
/ci run |
|
✅ Triggered Buildkite CI #98614 for commit ℹ️ This PR is 13 commits behind upstream |
Check the MoE backend before reading parallel_config, and take the token count from the hidden states, so model construction and forward work for configs (and test stubs) that never enable sequence parallelism. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Thien Tran <gau.nernst@yahoo.com.sg>
Contributor
Author
|
/ci retry |
|
✅ Triggered Buildkite CI #98679 for commit |
zyongye
approved these changes
Nov 2, 2026
This was referenced Nov 3, 2026
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.
Overview
This PR adds sequence parallelism (SP) to MiniMax-M3 on NVIDIA when running TP + EP with the MegaMoE backend, plus the GEMM-RS kernel for
o_projand the dense MLPdown_proj. The design follows the existing Kimi-K3 and DeepSeek-V4.1 SP.Without SP, MegaMoE already shards tokens across TP ranks internally, but then writes its shard into a zero-filled full-size buffer, and the next RMSNorm all-reduces it. So every layer pays 2 full all-reduces: one after attention, and one on a mostly-zero MoE output. With SP, the residual stream stays sharded by token, and each MoE layer does 1 all-gather before attention and 1 reduce-scatter after
o_proj. MegaMoE consumes the shard directly. The 3 dense layers do one more all-gather/reduce-scatter pair around their MLP.Claims
VLLM_ENABLE_GEMM_RS=1.MiniMaxAI/MiniMax-M3.1-Flash(8k in / 1k out, DSpark spec decode), compared to TP4 + EP without SP:Validation
All benchmarks were done on a single 4×GB300 node, with
f81a414faeas the base andMiniMaxAI/MiniMax-M3.1-Flash(9e7ebac). The serve command is the "Single node (TP4, NVIDIA GB200)" command from the vLLM recipe, plus--no-enable-prefix-caching. 3 setups are compared:-ep --moe-backend deep_gemm_mega_moe, on mainVLLM_ENABLE_GEMM_RS=1, on this PRServe command (TP4 + EP + SP)
E2E: SpeedBench throughput_8k
The full sweep was run twice for each setup, restarting the server in between. Each cell is the range over the 2 runs; best (by mean) in bold.
Output throughput
P50 TTFT
P50 TPOT
As expected, pure TP4 is the fastest at low concurrency, and EP pulls ahead at high concurrency. SP lowers TTFT at every concurrency, with no overlap between the ranges, and widens EP's lead in throughput at concurrency 16 and 64. At concurrency 4 and for TPOT at concurrency 16, the SP and EP ranges overlap, so those are a tie.
At concurrency 1, TPOT is 3% higher with SP. This comes from spec decode acceptance (3.10 vs 3.20), not from slower steps: TPOT × acceptance length is the same (8.56 ms vs 8.58 ms). Concurrency 1 only has 10 prompts, so a small numerical difference in the outputs is enough to change the acceptance length. It was identical in both runs.
Acceptance length (mean of 2 runs)
Accuracy
gsm8k, 5-shot, chat completions, temperature 0. One eval per server start (run 1 / run 2).
GEMM-RS microbenchmark
TP4, N=6144. Baseline is the existing unfused path in vLLM (MXFP8 GEMM +
sp_reduce_scatter).M=512-1536 was repeated two more times. GEMM-RS was faster at M ≥ 1024 every time, while M=768 was mixed, so GEMM-RS is only used for M ≥ 1024.
Above 1024 tokens, the fused dense GEMM1 hands
down_projan MXFP8QuantizedActivation, so the BF16-input numbers above include an activation quantization that production skips. Re-measured with the same pre-quantized input for both paths (range over 2 runs):GEMM-RS stays faster at every M above the threshold.
Tests
tests/kernels/test_gemm_rs_ar.py: extended with a pre-quantized MXFP8 input for both MXFP8 backends. Passes on 2×GB300. CI runs it in the 2×B200 distributed step.Details
Changes in
vllm/models/minimax_m3/nvidia/model.py:o_proj+sp_reduce_scatter, or GEMM-RS).input_is_sequence_sharded), so no shard/gather/zero-fill. The existinguse_sequence_parallelflag inMiniMaxM3MoEis renamed toshard_replicated_input, since it means the opposite of model-level SP.gate_up(keeps the fused dense GEMM1) anddown_proj, then reduce-scatter.GEMM-RS with a quantized input Above its token threshold, the fused dense GEMM1 outputs an MXFP8
QuantizedActivationinstead of BF16. SoGemmRsAr.apply()now accepts it and skips its own quantization. The scales are already in the F8_128x4 swizzled layout that the kernel expects.Limitations and follow-ups
qkv_projinput instead would halve the bytes; this is left for a follow-up.AI assistance (Claude) was used to write this change and to run the validation above.
Pull Request Checklist
I used vLLM's
/pr-checklistskill. (Mandatory for agents, optional for humans).AI assistance was used during the creation of this PR.
Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.
Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.
Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.
Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.
🤖 Generated with Claude Code