Add SM90 MegaMoE by cooperative - #360
Open
mpdfdfl wants to merge 19 commits into
Open
Conversation
Two SM90 (Hopper) FP8 MegaMoE kernels with their own scheduler and
heuristics, kept isolated from the shared SM100 mega_moe scheduler/heuristics
so the SM100 path is untouched:
* pingpong (BLOCK_M=64): one math warpgroup per tile, the two warpgroups
overlap one's MMA with the other's epilogue via an OrderedSequenceBarrier.
Tuned for small/medium M.
* cooperative (BLOCK_M=128): the two math warpgroups cooperatively M-split a
single tile and share one B-tile load, halving weight HBM traffic; a
256-thread cross-warpgroup barrier closes the L2 epilogue. Tuned for large M.
New files: impls/sm90_fp8_mega_moe_{pingpong,cooperative}.cuh, the SM90 host
runtimes, scheduler/sm90_mega_moe.cuh (adds kClusterSize / kL2NMajorSchedule),
and heuristics/sm90_mega_moe.hpp.
Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
Wire the two SM90 kernels into the host API and Python:
* csrc/apis/mega.hpp: SM90-aware get_symm_buffer_size_for_mega_moe (per-arch
SF dtype/granularity, guarded by is_sm90 so the SM100 path is unchanged);
fp8_mega_moe routes by token count (DG_SM90_MOE_COOPERATIVE_THRESHOLD,
default 256) between pingpong (<threshold) and cooperative (>=threshold);
plus fp8_mega_moe_{pingpong,cooperative} forced entry points for A/B.
* deep_gemm/mega/__init__.py + deep_gemm/__init__.py: expose fp8_mega_moe,
fp8_mega_moe_{pingpong,cooperative} and transform_weights_for_mega_moe_sm90.
* comm/barrier.cuh: guard the NVLink-timeout printf behind DG_NO_DEVICE_PRINTF
(defined by the SM90 kernels) to avoid the ptxas C7510 WGMMA-pipeline
serialization a function-call boundary would cause; upstream 300s timeout
is preserved.
Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
* tests/test_mega_moe_sm90.py: layered correctness suite (L1 smoke .. L5
stress) against a PyTorch reference via calc_diff. DG_SM90_MOE_KERNEL
selects auto / pingpong / cooperative.
* tests/bench_mega_moe_sm90.py: per-config TFLOPS / HBM / NVLink timing with
an optional DeepEP (V1 contiguous + V2 ElasticBuffer) baseline comparison.
* tests/_deepep_v1_baseline.py: the DeepEP V1 contiguous baseline used by the
bench (Triton SwiGLU + FP8 quant + grouped GEMM pipeline).
Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
Two SM90 (Hopper) FP8 MegaMoE kernels with their own scheduler and
heuristics, kept isolated from the shared SM100 mega_moe scheduler/heuristics
so the SM100 path is untouched:
* pingpong (BLOCK_M=64): one math warpgroup per tile, the two warpgroups
overlap one's MMA with the other's epilogue via an OrderedSequenceBarrier.
Tuned for small/medium M.
* cooperative (BLOCK_M=128): the two math warpgroups cooperatively M-split a
single tile and share one B-tile load, halving weight HBM traffic; a
256-thread cross-warpgroup barrier closes the L2 epilogue. Tuned for large M.
New files: impls/sm90_fp8_mega_moe_{pingpong,cooperative}.cuh, the SM90 host
runtimes, scheduler/sm90_mega_moe.cuh (adds kClusterSize / kL2NMajorSchedule),
and heuristics/sm90_mega_moe.hpp.
Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
Wire the two SM90 kernels into the host API and Python:
* csrc/apis/mega.hpp: SM90-aware get_symm_buffer_size_for_mega_moe (per-arch
SF dtype/granularity, guarded by is_sm90 so the SM100 path is unchanged);
fp8_mega_moe routes by token count (DG_SM90_MOE_COOPERATIVE_THRESHOLD,
default 256) between pingpong (<threshold) and cooperative (>=threshold);
plus fp8_mega_moe_{pingpong,cooperative} forced entry points for A/B.
* deep_gemm/mega/__init__.py + deep_gemm/__init__.py: expose fp8_mega_moe,
fp8_mega_moe_{pingpong,cooperative} and transform_weights_for_mega_moe_sm90.
* comm/barrier.cuh: guard the NVLink-timeout printf behind DG_NO_DEVICE_PRINTF
(defined by the SM90 kernels) to avoid the ptxas C7510 WGMMA-pipeline
serialization a function-call boundary would cause; upstream 300s timeout
is preserved.
Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
* tests/test_mega_moe_sm90.py: layered correctness suite (L1 smoke .. L5
stress) against a PyTorch reference via calc_diff. DG_SM90_MOE_KERNEL
selects auto / pingpong / cooperative.
* tests/bench_mega_moe_sm90.py: per-config TFLOPS / HBM / NVLink timing with
an optional DeepEP (V1 contiguous + V2 ElasticBuffer) baseline comparison.
* tests/_deepep_v1_baseline.py: the DeepEP V1 contiguous baseline used by the
bench (Triton SwiGLU + FP8 quant + grouped GEMM pipeline).
Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
mpdfdfl
force-pushed
the
sm90-mega-moe-pingpong-coop
branch
from
June 17, 2026 08:54
1380676 to
ec757bd
Compare
|
hi, which machine are you working on, h20, h100 or h200? |
Author
we working on H200 |
Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
Replace mega MoE implementation with the per-128 N-split cooperative kernel; keep remote .gitignore. Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
Drop the sglang MiMo-V2-flash fidelity test; it depends on an external sglang source tree and preset checkpoint that are not part of this repo. Co-Authored-By: OpenDarrenlu <2945034270@qq.com>
mpdfdfl
force-pushed
the
sm90-mega-moe-pingpong-coop
branch
2 times, most recently
from
July 16, 2026 14:25
e2050ed to
f983307
Compare
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.
Add SM90 MegaMoE (cooperative)
Co-Authored-By: @OpenDarrenlu
First, thanks to #352 and #323 — this work builds on the ideas from those PRs.
We provide the SM90 fused MegaMoE through a single cooperative kernel
(
BLOCK_M=64,BLOCK_N=256). The two math warpgroups cooperatively N-split onetile — the first warpgroup owns the left 128 columns and the second owns the
right 128 columns (each an
m64n128WGMMA) — and share a single A-tile (weight)load.
Why cooperative-only, and why the 64×256 tiling
We discovered an accuracy issue during end-to-end testing. We suspect the cause
is that the L1 output of the MoE layer is normally quantized per-128, whereas
our earlier implementation quantized it per-64. To fix this, we settled on a
single cooperative kernel in which the first warpgroup handles the left 128
columns and the other handles the right 128 columns, so the post-SwiGLU L1 output
is quantized per-128 (matching the standard DeepEP runner's
scale_block_size=128). At the same time, we were pleasantly surprised to findthat with this layout the cooperative implementation also delivers better
performance at small shapes.
As a result, the former pingpong kernel and the token-count routing threshold
were removed —
fp8_mega_moenow always runs the cooperative kernel.fp8_mega_moe_cooperativeis kept as an explicit named entry for A/B testing.The SM90 kernel / scheduler / heuristics are kept separate from the shared SM100
files, so SM100 behavior is unchanged.
Correctness test
tests/test_mega_moe_sm90.pychecks the fused kernel against a PyTorch reference(
calc_diff < 0.01) over layered scenarios (smoke → shapes → edge cases →random stress).
Benchmark
tests/bench_mega_moe_sm90.pytimes the fused kernel end-to-end against theDeepEP + DeepGEMM unfused baselines (V1 contiguous, V1 low-latency, V2
ElasticBuffer), same CUDA-event timing for all.
Here are our latest test results.
1. Single-operator benchmark (vs. deepep)
Shape — hidden=4096, moe_intermediate=2048, experts=256, topk=8 (MiMo-V2.5)
2. End-to-end prefill benchmark
Setup: input 16K, output 1, TTFT capped within 1s.
📈 Compared with deepep, input token throughput improves by 25% (86653 vs 69635 tok/s).
3. Decode benchmark
Since this is a single-node deployment, TPOT is derived from the logs.
TODO / future work
This is just a first version, and there is still a lot of room to optimize
inside the kernel. We would really love your help — let's optimize this kernel
together! Planned directions:
tuning the block-tile / expert-wave scheduling strategy should reduce HBM
traffic and help the large-M DRAM-bandwidth-bound cases.
MoE into focused kernels (dispatch+L1+SwiGLU / L2+combine / combine-reduce)
running concurrently on disjoint SM partitions via CUDA green contexts — to
overlap stages the fused megakernel serializes internally.