Skip to content

[JIT Kernel] Triton moe fused gate - #25835

Merged
BBuf merged 10 commits into
sgl-project:mainfrom
DarkSharpness:jit_moe_gate
Jun 30, 2026
Merged

BBuf merged 10 commits into
sgl-project:mainfrom
DarkSharpness:jit_moe_gate

Conversation

@DarkSharpness

@DarkSharpness DarkSharpness commented May 20, 2026 •

Copy link
Copy Markdown
Collaborator

Motivation

Modifications

Accuracy Tests

Speed Tests and Profiling

Details

H200

--- scoring_func=sigmoid ---
router-triton-sigmoid:
    num_tokens  num_experts     Triton   JIT CUDA   AOT CUDA     PyTorch
0          1.0        128.0   1.834210   3.927602   4.443029   11.444891
1          1.0        256.0   2.363654   4.307817   4.669247   11.935520
2          1.0        384.0   3.074000   4.430672   4.228168   13.438769
3          1.0        512.0   2.904917   4.643208   9.930292   14.397827
4          4.0        128.0   2.089324   4.166956   4.625003   12.005083
5          4.0        256.0   2.423767   4.386662   5.083536   13.375701
6          4.0        384.0   3.137502   4.551838   4.318706   14.302606
7          4.0        512.0   2.999984   4.765056  11.205966   15.195277
8         16.0        128.0   1.959985   4.283287   5.339957   13.659911
9         16.0        256.0   2.479789   4.453794   7.388555   13.622364
10        16.0        384.0   3.185441   4.571988   4.364245   15.169286
11        16.0        512.0   3.053365   4.796509  15.107861   15.933297
12        64.0        128.0   2.163168   4.327351   9.149960   13.873367
13        64.0        256.0   2.514072   4.522284   9.660589   14.278464
14        64.0        384.0   3.223618   4.633137   4.413351   16.675877
15        64.0        512.0   3.087926   4.853125  15.372105   16.824392
16       512.0        128.0   2.544322   4.713783   9.265528   16.061627
17       512.0        256.0   3.007975   5.757673  10.003918   19.265896
18       512.0        384.0   3.765571   7.136753   6.260274   23.358232
19       512.0        512.0   3.637413   8.824948  15.745529   26.847843
20      1024.0        128.0   3.254429   5.811557   9.639303   19.904962
21      1024.0        256.0   3.849963   7.732535  10.513669   28.665121
22      1024.0        384.0   4.720523   9.759010   7.180663   34.882308
23      1024.0        512.0   4.572790  11.613674  15.839016   42.483599
24      8192.0        128.0  12.319019  14.683194  15.458704   75.413761
25      8192.0        256.0  13.090187  18.738350  22.507664  134.071936
26      8192.0        384.0  20.068564  22.686620  22.678794  189.567994
27      8192.0        512.0  19.024397  26.745163  62.045582  195.311047

--- scoring_func=sqrtsoftplus ---
router-triton-sqrtsoftplus:
    num_tokens  num_experts     Triton   JIT CUDA  AOT CUDA     PyTorch
0          1.0        128.0   2.049909   4.034059       NaN   11.539094
1          1.0        256.0   2.463240   4.220677       NaN   12.073249
2          1.0        384.0   3.105660   4.349625       NaN   12.785801
3          1.0        512.0   3.123326   4.571196       NaN   13.364572
4          4.0        128.0   2.126329   4.086547       NaN   12.086154
5          4.0        256.0   2.519073   4.309747       NaN   13.515579
6          4.0        384.0   3.165996   4.468654       NaN   14.101261
7          4.0        512.0   3.184262   4.688678       NaN   14.222308
8         16.0        128.0   2.170266   4.191982       NaN   13.029426
9         16.0        256.0   2.574442   4.357929       NaN   14.512648
10        16.0        384.0   3.213447   4.495805       NaN   14.272284
11        16.0        512.0   3.230986   4.717884       NaN   15.596996
12        64.0        128.0   2.199725   4.252539       NaN   13.948073
13        64.0        256.0   2.610388   4.432298       NaN   14.726579
14        64.0        384.0   3.251474   4.556690       NaN   14.842500
15        64.0        512.0   3.271010   4.778395       NaN   15.859981
16       512.0        128.0   2.589421   4.662937       NaN   15.442306
17       512.0        256.0   3.101812   5.841424       NaN   18.763094
18       512.0        384.0   3.787065   7.326766       NaN   23.228571
19       512.0        512.0   3.775065   9.055400       NaN   28.659381
20      1024.0        128.0   3.430943   5.527650       NaN   19.787610
21      1024.0        256.0   3.999657   7.348811       NaN   27.382386
22      1024.0        384.0   4.851534   9.136948       NaN   34.851170
23      1024.0        512.0   4.862848  10.912049       NaN   42.139699
24      8192.0        128.0  12.492488  15.084052       NaN   74.736973
25      8192.0        256.0  14.154138  20.088078       NaN  132.876183
26      8192.0        384.0  23.564515  25.032667       NaN  190.762614
27      8192.0        512.0  21.298923  30.070126       NaN  195.498675

B200

--- scoring_func=sigmoid ---
router-triton-sigmoid:
    num_tokens  num_experts  Triton (us)  JIT CUDA (us)  AOT CUDA (us)  PyTorch (us)
0          1.0        128.0     1.396091       4.103356       6.684546     11.940483
1          1.0        256.0     1.834877       4.453241       6.918450     12.336925
2          1.0        384.0     2.688935       4.626778       4.730553     13.807374
3          1.0        512.0     2.697143       4.613904      10.725232     14.636365
4          4.0        128.0     1.521778       4.323476       6.844504     12.758594
5          4.0        256.0     1.891310       4.463680       7.316693     13.925247
6          4.0        384.0     2.753923       4.627114       4.793807     15.103689
7          4.0        512.0     2.791018       4.815287      12.036858     15.899418
8         16.0        128.0     1.411671       4.322597       7.649889     13.759096
9         16.0        256.0     1.895599       4.462113       9.425854     14.000566
10        16.0        384.0     2.753475       4.626897       4.794151     15.529585
11        16.0        512.0     2.811916       4.816156      16.666132     16.403332
12        64.0        128.0     1.544356       4.325425      10.907519     14.222517
13        64.0        256.0     1.931545       4.472175      11.474394     14.409488
14        64.0        384.0     2.778786       4.642815       4.846269     16.933204
15        64.0        512.0     2.829662       4.862670      18.760702     16.899242
16       512.0        128.0     1.842751       4.743681      11.390199     15.895147
17       512.0        256.0     2.263072       5.816876      11.883010     18.705304
18       512.0        384.0     3.103908       7.349855       7.137295     23.296915
19       512.0        512.0     3.198217       8.979022      20.002183     27.140700
20      1024.0        128.0     2.429423       4.875137      11.342573     18.431245
21      1024.0        256.0     2.876668       5.986110      12.167687     25.338667
22      1024.0        384.0     3.981719       7.452341      21.203750     32.626606
23      1024.0        512.0     4.101471       8.632410      21.247204     42.675032
24      8192.0        128.0    10.009394      11.518002      17.049050     66.574534
25      8192.0        256.0    10.601710      14.093436      23.837060    119.095065
26      8192.0        384.0    17.014815      17.389482      60.424990    176.184521
27      8192.0        512.0    18.148243      20.826700      54.573896    205.863378

--- scoring_func=sqrtsoftplus ---
router-triton-sqrtsoftplus:
    num_tokens  num_experts  Triton (us)  JIT CUDA (us)  AOT CUDA (us)  PyTorch (us)
0          1.0        128.0     1.504107       4.322154            NaN     11.959668
1          1.0        256.0     2.022389       4.483059            NaN     12.506618
2          1.0        384.0     3.025733       4.654980            NaN     13.084887
3          1.0        512.0     2.953672       4.851780            NaN     13.657991
4          4.0        128.0     1.560420       4.347018            NaN     12.762579
5          4.0        256.0     2.076152       4.492601            NaN     14.307470
6          4.0        384.0     3.091817       4.657457            NaN     15.031335
7          4.0        512.0     3.005159       4.851272            NaN     15.127033
8         16.0        128.0     1.570828       4.349176            NaN     13.625110
9         16.0        256.0     2.084188       4.491607            NaN     15.143273
10        16.0        384.0     2.898157       4.658110            NaN     14.807826
11        16.0        512.0     3.023339       4.854286            NaN     16.496621
12        64.0        128.0     1.584414       4.351182            NaN     14.471663
13        64.0        256.0     2.117914       4.501853            NaN     14.958539
14        64.0        384.0     3.118461       4.672287            NaN     15.703535
15        64.0        512.0     3.040645       4.896086            NaN     16.616582
16       512.0        128.0     1.783925       4.805308            NaN     15.447982
17       512.0        256.0     2.450871       6.011256            NaN     18.556082
18       512.0        384.0     3.441797       7.562089            NaN     24.211746
19       512.0        512.0     3.407195       9.341411            NaN     27.985634
20      1024.0        128.0     2.473149       5.062175            NaN     18.563698
21      1024.0        256.0     2.923180       6.334446            NaN     25.445477
22      1024.0        384.0     4.334769       7.954241            NaN     34.714734
23      1024.0        512.0     4.396394       9.293829            NaN     42.614986
24      8192.0        128.0    10.190486      12.361880            NaN     64.970773
25      8192.0        256.0    11.986645      15.915424            NaN    118.424098
26      8192.0        384.0    19.047844      20.134156            NaN    179.851325
27      8192.0        512.0    19.736000      23.431825            NaN    210.407163

Checklist

Review and Merge Process

  1. Ping Merge Oncalls to start the process. See the PR Merge Process.
  2. Get approvals from CODEOWNERS and other reviewers.
  3. Trigger CI tests with comments or contact authorized users to do so.
    • Common commands include /tag-and-rerun-ci, /tag-run-ci-label, /rerun-failed-ci
  4. After green CI and required approvals, ask Merge Oncalls or people with Write permission to merge the PR.

CI States

Latest PR Test (Base): ❌ Run #28449799244
Latest PR Test (Extra): ❌ Run #28449798503

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request introduces a Triton-based implementation of the MoE fused gate kernel, supporting scoring functions like sigmoid and sqrtsoftplus along with bias, top-k selection, and optional renormalization. The changes include a new benchmark suite, unit tests comparing the Triton implementation against PyTorch and CUDA JIT references, and integration into the MoE top-k layer. Review feedback recommends using built-in Triton functions such as tl.sigmoid and tl.log1p for improved readability and numerical precision, as well as cleaning up placeholder text in code comments.

Comment thread python/sglang/jit_kernel/moe_fused_gate.py Outdated
Comment thread python/sglang/jit_kernel/moe_fused_gate.py
Comment thread python/sglang/jit_kernel/moe_fused_gate.py Outdated
@yuan-luo

Copy link
Copy Markdown
Collaborator

/tag-and-rerun-ci

@github-actions github-actions Bot added the run-ci CI: run the baseline test suite on this PR label May 20, 2026
@yuan-luo

Copy link
Copy Markdown
Collaborator

/tag-and-rerun-ci

Comment thread python/sglang/jit_kernel/moe_fused_gate.py Outdated
@ispobock

Copy link
Copy Markdown
Collaborator

ref #26771 cc @BBuf

Comment thread test/registered/jit/test_moe_fused_gate.py

@BBuf BBuf left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add some model acc test?

@yuan-luo

yuan-luo commented Jun 7, 2026

Copy link
Copy Markdown
Collaborator

/rerun-failed-ci

claude and others added 7 commits June 10, 2026 09:39
Add a Triton implementation of the fused MoE router (scoring + bias +
top-k + optional renormalize/scale) in jit_kernel/moe_fused_gate.py, and
route the ungrouped CUDA path (DeepSeek-V4 / Kimi-K2, num_expert_group=1)
through it in topk.py, replacing the AOT kimi_k2_moe_fused_gate kernel.

The Triton kernel mirrors the CUDA fused-gate semantics: sigmoid /
sqrtsoftplus scoring, lowest-id tie-break, fused shared experts, and PDL
launch on supported arches. It is a single-warp, one-program-per-row
kernel and benchmarks faster than the JIT/AOT CUDA and PyTorch baselines.

Tests validate against a definition-based torch reference, the CUDA JIT
kernel it reimplements, and the production biased_grouped_topk_impl for
the path it replaces; comparisons are order-independent (scatter-by-expert).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
moe_fused_gate_kernel_small_token<kWarpsPerToken> is launched with
blockDim.x = div_ceil(num_experts, 32) * 32 warps, which can be fewer
than the template upper bound kWarpsPerToken (e.g. num_experts=128 -> 4
warps under the <8> instantiation). The cross-warp reduction read
warp_maxs/warp_experts for lanes up to kWarpsPerToken, including slots
that were never written, yielding a garbage winning expert id and an
out-of-bounds shared-memory read. This is undefined behavior that
surfaced as an illegal-instruction fault under repeated CUDA-graph
replay in the benchmark.

Read only the warps that were actually launched (blockDim.x / warpSize).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Use the jit_kernel benchmark `marker` framework (parametrize/benchmark/
do_bench) instead of triton.testing.perf_report. marker keeps the L2
cache cold by cloning the read args across CUDA-graph replays, so the
manual layer-rotation trick is no longer needed, and it reports memory
bandwidth alongside latency. AOT providers are marker.skip()-ed for the
sqrtsoftplus scoring they do not implement.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…path

triton.language has no `log1p` attribute (neither tl.log1p nor
tl.math.log1p exist in the CI/runtime Triton version), causing a
CompilationError for the sqrtsoftplus scoring path. Restore the
original tl.log(1.0 + tl.exp(scores)) formulation (equivalent to
log1p(exp(x)), already guarded against overflow by the scores > 20
branch).
main now relocates all JIT-kernel tests under test/registered/ and enforces it
via scripts/ci/check_no_registered_tests_in_package.py (registered tests inside
the importable sglang package would be shipped in the wheel and silently
dropped by run_suite.py). Move the two files this PR adds to match:
  python/sglang/jit_kernel/tests/test_moe_fused_gate.py
    -> test/registered/jit/test_moe_fused_gate.py
  python/sglang/jit_kernel/benchmark/bench_moe_fused_gate.py
    -> test/registered/jit/benchmark/bench_moe_fused_gate.py

Verified on B200: test_moe_fused_gate 971/971 passed; package-test guard passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@DarkSharpness

Copy link
Copy Markdown
Collaborator Author

(generated by claude)

Rebased onto latest main (the topk.py 384-expert path merged cleanly this time). One rebase-consistency fix was required: main now relocates all JIT-kernel tests under test/registered/ and enforces it via scripts/ci/check_no_registered_tests_in_package.py (a registered test left inside the sglang package gets shipped in the wheel and silently dropped by run_suite.py). So this PR's two new files were moved:

  • …/jit_kernel/tests/test_moe_fused_gate.py → test/registered/jit/test_moe_fused_gate.py
  • …/jit_kernel/benchmark/bench_moe_fused_gate.py → test/registered/jit/benchmark/bench_moe_fused_gate.py

On the review threads:

  • @BBuf (acc test) / @ispobock (PDL on/off correctness): test_moe_fused_gate.py already parametrizes PDL on/off × scoring_func (sigmoid + sqrtsoftplus) × num_expert_group × num_experts {128,256,384,512} × tokens, checking the Triton kernel against both a torch reference and the CUDA-JIT moe_fused_gate. Ran the full suite on B200: 971/971 passed (482 of them sqrtsoftplus).
  • @gemini (tl.sigmoid): already applied — the kernel uses tl.sigmoid.
  • @gemini (tl.log1p): not applied — tl.log1p does not exist in the pinned Triton (AttributeError: module 'triton.language' has no attribute 'log1p', confirmed by a failed compile across all 482 sqrtsoftplus cases), so the tl.log(1.0 + tl.exp(x)) form with the x > 20 overflow guard is kept.

Full moe_fused_gate suite green locally; pushing for fresh CI.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@BBuf

BBuf commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

/rerun-failed-ci

@BBuf BBuf added the run-ci-extra CI: also run the extra suite (requires run-ci) label Jun 30, 2026
@BBuf

BBuf commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

/tag-and-rerun-ci

BBuf and others added 2 commits June 30, 2026 17:33
…/runner_config

The registered-test validator rejects the legacy single-string
`suite="{stage}-test-{runner_config}"`-shaped form for new CUDA tests
(not dispatchable via /rerun-test), failing lint + build-test. Switch
test_moe_fused_gate.py and bench_moe_fused_gate.py to the modern
`stage=`/`runner_config=` form, matching the sibling dsv3 kernel tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@BBuf
BBuf merged commit cf36dca into sgl-project:main Jun 30, 2026
120 of 164 checks passed
vstone-w pushed a commit to ClownBin/sglang that referenced this pull request Jul 2, 2026
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: ziyi.xu <ziyi.xu@radixark.ai>
Co-authored-by: Xiaoyu Zhang <1182563586@qq.com>
@qiushixiaoyu

Copy link
Copy Markdown
Contributor

@DarkSharpness
Numerical regression on DeepSeek-V4 (sqrtsoftplus) + FP8 MegaMoE bisected to this PR

Thanks for this kernel! We hit an accuracy regression that git bisect points to this PR (cf36dca), and wanted to share the findings in case they're useful.

Setup

Model: DeepSeek-V4-Flash-FP8 — scoring_func=sqrtsoftplus, 256 routed experts, ungrouped, topk=6.
Serving: SM90 (Hopper) all-FP8 MegaMoE path (DeepGEMM mega_moe runner), TP8 / DP8 / EP8, EAGLE spec-decode, thinking enabled.
Eval: GPQA-diamond (198 q), temp=1.0 / top_p=1.0 / max_tokens=200k.
Symptom

After this PR, GPQA pass@1 drops from ~88% to ~74–82%, and the no_answer rate rises from 0 to ~7–12% (empty / early-stopped generations — predicted_answer=None with finish_reason=stop, i.e. not max-token truncation). Failures concentrate on long (thinking) decodes.
Where it comes from

This PR replaces the AOT CUDA gate kernel (moe_fused_gate_jit) with the Triton _router_triton_kernel for the sqrtsoftplus path.
The Triton router's per-expert scores differ from the AOT kernel by ~1e-4. A reasoning-level dump shows e.g. topk_weights 0.0093 (Triton) vs 0.0092 (AOT), and within a few layers the tie-break selects a different expert (topk_ids flip).
The gate output is identical for the DeepEP and MegaMoE paths, but only MegaMoE regresses (no_answer stays 0 on DeepEP). So the ~1e-4 gate difference appears to be amplified specifically by the fused FP8 MegaMoE kernel, while DeepEP absorbs it.
What restores accuracy

Routing the gate through the torch reference path (SGLANG_OPT_USE_JIT_KERNEL_FUSED_TOPK=0) or back through the AOT kernel fully recovers it (no_answer → 0, pass@1 → ~88–91%).
On the exact cause (not fully pinned down)

We tried swapping the Triton tl.exp/tl.log for the precise libdevice variants (tl.extra.cuda.libdevice.exp/log). This only partially helped (no_answer ~9% → ~6%, still not 0), so the approximate exp lowering looks like a contributor but not the sole source. We have not conclusively isolated the difference — other candidates that differ structurally between the Triton and AOT implementations include log1p vs log(1+exp), the reduction order in the top-k sum, and the tie-break rule. Sharing this so it doesn't get mis-attributed to a single cause.
Would be great to have

A way to keep the sqrtsoftplus gate numerically aligned with the pre-#25835 AOT kernel — e.g. an option to select the AOT / precise path, or tightening the Triton router's sqrtsoftplus numerics. For now we're pinning SGLANG_OPT_USE_JIT_KERNEL_FUSED_TOPK=0 for MegaMoE as a stopgap.
Happy to share dumps / a repro if helpful.

Chronostasys pushed a commit to MindLab-Research/sglang that referenced this pull request Aug 24, 2026
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: ziyi.xu <ziyi.xu@radixark.ai>
Co-authored-by: Xiaoyu Zhang <1182563586@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jit-kernel run-ci CI: run the baseline test suite on this PR run-ci-extra CI: also run the extra suite (requires run-ci)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants