Conversation
The Triton router kernel prefetched `bias` before `gdc_wait()` and loaded `scores` after it. The bias is not an immutable input: `fused_topk` passes a buffer written by the immediately preceding kernel (a dtype cast of the correction bias today; a fresh `torch.zeros` before sgl-project#36811). Under programmatic dependent launch the router can start once that kernel's blocks exit, before its stores are visible, so the pre-wait load could read the buffer's previous contents. On DGX Spark (GB10) with Qwen3.8-Flash-Next NVFP4 + NEXTN this surfaced as batch-wide NaN routing weights and an output collapse to token 0 (sgl-project#37111). Move the wait above the bias load so every dependent load sits after it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Same ordering defect as in the Triton router: route_radix_block prefetched the bias before PDLWaitPrimary(), assuming a frozen weight, but the public moe_fused_gate dispatches covered sigmoid inputs here with a bias that can be a fresh fp32 cast or a fresh torch.zeros. Move the wait above the load. Also shorten the Triton kernel comment to state only what is established. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This was referenced Sep 9, 2026
Jiminator
marked this pull request as ready for review
September 11, 2026 21:06
Jiminator
requested review from
BBuf,
DarkSharpness,
HaiShaw,
HydraQYH,
celve and
yuan-luo
as code owners
September 11, 2026 21:06
5 tasks
Collaborator
Author
|
Superseded by combined draft PR #39126, which preserves all three component changes and includes the DGX Spark MTP/non-MTP accuracy and throughput results. Closing this separate PR in favor of the combined review. |
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
PDL-launched routers can read a stale bias produced by a preceding cast or fill kernel. Both the Triton router and radix router currently load bias before waiting for the PDL dependency, although scores are loaded after the wait. The sigmoid/grouped callers can supply freshly cast bias tensors, so this is not limited to Qwen.
Upstreams #38290 onto
mainafter #37500. Related reports: #37111 and #37052.Modifications
Move the existing dependency wait ahead of both input loads in the Triton and radix kernels. No additional allocation, launch, load, or wait. The no-bias path continues to use register zeros.
Accuracy Tests
September 11, 2026: current-main combined deployment validation
Tested #38568 + #38569 + #38570 together on
main@165d8dd17736fa4938f2e73018f26835cd6e0778, combined merge69d38ccbd8a03646cae9168c971b3783883c2903. PR heads: #38568626f614f7bcd5dc531de5c268a694ff1a9f31f28, #38569825663897b1fd9ee5c341eeb113b795e4ecfc3f8, #38570b14d2c55f37f8d3dc2b5fe21175b56fbe62771e1. All merged cleanly; no additional source fixes were needed.Native host installation on 1x DGX Spark / GB10, TP=1, rebuilt from the merged checkout without a patched Docker image. Model:
nvidia/Qwen3.8-Flash-Next-NVFP4, checkpoint revisionfab0aecb760cec45227f6656abcaafa11abca87a. GSM8K first 200 test questions, greedy chat API, thinking disabled, 8,192-token generation limit:Both smoke responses were correct and CUDA graphs were active. MTP used the expected FP8 Triton expert fallback and reported average draft acceptance 3.52925. No serving NaN/OOM/CUDA-error/exception reports appeared before intentional shutdown; shutdown cancellation diagnostics were recorded separately.
Serving flags: TP=1, FlashInfer CUTLASS MoE/FP4 backends, page size 64, chunked prefill 4096, requested context 262144, static memory fraction 0.85, and file-backed PLE with a fresh local-NVMe file per boot. MTP: NEXTN, 3 steps, top-k 1, 4 draft tokens, 8 maximum requests, 40 Mamba slots. Non-MTP: extra_buffer_lazy, 24 maximum requests, 96 Mamba slots.
The isolated host environment was updated from current main and native extensions rebuilt (PyTorch 2.13.0+cu130, FlashInfer 0.6.18, Triton 3.7.1, sglang-kernel 0.4.6.post1, Transformers 5.12.1). Runs reused previously compiled host kernels with
MAX_JOBS=2; startup timings exclude cold kernel compilation. Throughput includes prefill and the lower-concurrency tail and is not an isolated measurement of this PR's speed impact.Scope: combined TP=1 deployment validation, not independent deterministic reproduction of the PDL race, TP>1 prefetch validation, or the full 1,319-question benchmark. Effective max input was 180,282 tokens with MTP and 262,138 without MTP; no full-length 262K prompt was tested. Both servers were stopped and their generated PLE files removed after evaluation.
Latest-main necessity check: source-reviewed
main@45715e7f20629d1813ff8f543a23bb437128db2eafter the deployment run. Both radix and Triton routers still load bias before their PDL dependency wait. The combined PRs merge cleanly onto this newer revision. The accuracy numbers above remain measurements of165d8dd177, not a GPU rerun on this newer base.Earlier validation
test_moe_fused_gate.pyreference comparisons, no-bias/zero-bias equivalence, and non-fp32 bias tests: 15 passed. These check routing semantics, not deterministic reproduction of the race.LDG.E.128instructions beforeACQBULK; fixed PTX hadgriddepcontrol.waitbefore all six global loads. During an instrumented collapse, all 23 bad rows in a 32-row target-verify step saw NaNs in the pre-wait bias and zeros on a post-wait reread, with settled scores unchanged.Combined deployment validation with #38569 and #38570 also passed on a fresh-host GB10: 200-question GSM8K samples scored 98.0% (MTP) / 97.0% (non-MTP) on base
52fecfdf09, with no invalid/capped answers or request errors. Both commands also booted and served 24-request sanity samples on newer basedb272201a2. Full environment and result details are in #38569. These combined model runs do not deterministically reproduce the bias-carrying PDL race.Speed Tests and Profiling
No new performance measurement on this port. The bias load no longer overlaps the preceding kernel's tail; the exposed load latency is per launch, not multiplied by row count. The plain-softmax no-bias path has no bias load. Performance on bias-carrying paths remains to be measured.
Checklist
CI States
Latest PR Test (Base): ❌ Run #34592943620
Latest PR Test (Extra): ❌ Run #34592943490
Latest PR Test (AMD ROCm 10): ❌ Run #34592943551