Skip to content

[Feat] nemotron: Port Nemotron 3.5 Super serving changes - #44518

Merged
BBuf merged 48 commits into
mainfrom
nemotron3-super-dev-20261015
Oct 19, 2026
Merged

BBuf merged 48 commits into
mainfrom
nemotron3-super-dev-20261015

Conversation

@Jiminator

@Jiminator Jiminator commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Bring Nemotron 3.5 Super MTP serving optimizations for SM120 into SGLang: small-M NVFP4 MoE execution, SM120 GEMV, FlashInfer host planning, and hybrid prefill CUDA graphs.

Scope

Validation

For this revision (4631e828b8), only CPU and static checks were run, on macOS:

  • git diff --check, the repository's pinned ruff 0.15.1 (hook rule selection and format check), isort 7.0.0, codespell 2.4.1, clang-format 20.1.7, check-ast, debug-statements, and the registered-test lint scripts all pass on the changed files.
  • A focused CPU check confirms the Nemotron-H MoE decoder layers, including the MTP layer, still pass forward_batch to the MoE core (the input the SM120 prefill-overlap gate reads). Results match the previous head d3f59dd9a6.
  • Eight CPU-registered Nemotron-H unit test files give identical results on this revision, the previous head and main. In each case 151 pass and 1 is skipped. The remaining 134 fail on all three in this Mac environment; sampled failures hit the Torch ≥ 2.13 MPS requirement (the available environment has Torch 2.11).

No GPU tests, E2E serving runs or benchmarks were run for this revision.

Historical E2E evidence (not rerun)

The measurements below come from earlier heads, before main was merged (d3f59dd9a6) and before the carried upstream changes were removed. Both measured heads still included the carried changes. They compare the earlier public head af2628444e with the cleanup head ce427d4d9b. Both ran on the same RTX PRO 6000 (SM120), EA1008 NVFP4 checkpoint, pinned container, launch settings and request token IDs. Settings: TP=1, concurrency=1, real EAGLE acceptance (3 steps / 4 draft tokens). Each run has two warmups and 80 measured requests of 8,192 input / 1,024 output tokens, with the prefix cache flushed before every measured request.

Check af2628444e ce427d4d9b
Output throughput 243.6717 tokens/s 242.6594 tokens/s
Mean TTFT 845.7203 ms 858.7892 ms
Mean TPOT 3.2812 ms 3.2856 ms
Mean acceptance length 3.9798 3.9798
Same fixed 100-question GSM8K slice 95/100 95/100

Throughput changed by -0.42% and TTFT by +13.07 ms (+1.55%). All 80 complete output-token sequences and all 100 GSM8K answer texts match exactly. Both runs had zero cached prompt tokens, zero request retractions, and no competing GPU process during measurement. The workload uses repeated text and has high acceptance. These results do not establish general conversational throughput or performance on other GPU architectures.

Earlier hardware recipes and model-support validation are recorded in cookbook PR #44510.

🤖 Generated with Claude Code


CI States

Latest PR Test (Base): 🚫 Run #39201116873
Latest PR Test (Extra): 🚫 Run #39201116823
Latest PR Test (AMD ROCm 10): ⏳ Run #39201116860

BBuf and others added 30 commits October 15, 2026 09:50
Splitting the global --max-running-requests across attention DP workers
used bare floor division, so `--max-running-requests 1 --dp 4` gave every
worker 0 slots. On hybrid models this surfaced as a misleading
"mamba state cache is too small" startup failure even though the mamba
pool had plenty of slots; the same floor division also produced 0-sized
mamba pools on the disable-radix-cache path. The MLX resolver, which
mirrors the same split, returned 0 unchecked outside its hybrid branch.

Floor every per-worker split at 1, matching the guard the DeepEP v2
dispatch budget check already had. Requests are load balanced across
workers, so a worker with 0 slots can never serve anything. The division
itself stays floored, so the request pool, the mamba pools, the PD
in-transfer reserve, the GDN ReplaySSM ring reserve, the LoRA MoE CUDA
graph buffers and the MLX resolver keep sizing from the same per-worker
count.

(cherry picked from commit f284c66)
Under MAX_LEN padding, prepare_mlp_sync_batch relabels a decoding DP rank
as EXTEND and pads each row to a 1-token extend, so every rank presents
one shape to the collectives.

The relabel only decouples tokens from rows for the DP collectives; the
rows stay decode rows. Consumers that need the decode semantics behind
the label now read back through the new ForwardBatch.logical_forward_mode
property:

  - mamba metadata, which would otherwise treat the rows as prefills,
    skipping the decode state tracking (num_decodes == 0) and
    dereferencing mamba_track_seqlens, which a decode batch never builds;
  - the KDA gate preprocessing in kimi_linear and kimi_k3, which would
    otherwise take the prefill branch and hand the decode kernel a
    [1, T, H, K] forget gate and a pre-sigmoided beta;
  - the GDN input layout in qwen3_5, which would otherwise hand the
    decode kernels the strided views built for prefill.

[Port note: resolved a comment-only conflict in kimi_linear.py. The base no
longer carries the "Prefill passes raw gates" comment, so only the new
logical-mode comment is kept, matching the upstream PR head.]

(cherry picked from commit 5e1c25d)
Cover KVCacheConfigurator.resolve_max_num_reqs and the SWA chunk cap with
--max-running-requests below attn_dp_size. Both sized each worker for zero
requests before the split was floored at one.

(cherry picked from commit 98c7a89)
Run a relabeled decode batch on a mamba track boundary through
MambaAttnBackendBase._forward_metadata, where the scheduler crash fired; the
existing cases only exercised Mamba2Metadata.prepare_mixed. Move those cases
into test_mamba_prefill_track_metadata.py alongside it.

(cherry picked from commit 28220ac)
@Jiminator
Jiminator marked this pull request as draft October 15, 2026 16:35
BBuf added 2 commits October 16, 2026 12:11
Keep the measured kernels and launch parameters while removing unused Mamba megakernel and L2 prefetch experiments. Consolidate related wrappers, move phase-layout ownership into the model, reuse derived-cache update guards, and retain numerical/graph tests.

Fix the prefill overlap TP lookup against the current runtime context.
@BBuf BBuf changed the title [Feat] Port Nemotron 3.5 Super serving changes [Feat] nemotron: Port Nemotron 3.5 Super serving changes Oct 16, 2026
BBuf added 3 commits October 17, 2026 20:48
Use the upstream TRTLLM workspace semaphore isolation instead of a
separate fmha_v2 allocation, retaining the prefill/decode regression test.
@BBuf
BBuf marked this pull request as ready for review October 17, 2026 14:07
@BBuf BBuf added run-ci CI: run the baseline test suite on this PR run-ci-extra CI: also run the extra suite (requires run-ci) labels Oct 17, 2026
Jimmy Shong and others added 3 commits October 18, 2026 00:22
The per-worker max_running_requests floor, ForwardBatch.logical_forward_mode
and its Mamba/KDA/GDN consumers, and their unit tests belong to #34535, which
is reviewed separately. Restore these files to main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main keeps fmha_v2 prefill out of XQA's workspace semaphores through #42930,
which superseded #42746. Restore the test file and its CI estimate to main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main's NemotronHMoEDecoderLayer.forward, added with Nemotron-H EPLB support,
already passes forward_batch to NemotronHMoE, so the prefill-overlap gate keeps
its input. The MLP-like helper's MoE branch is unreachable; restore the base
forward.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep the upstream removal of unused JIT MoE gate wrappers while preserving the SM120 small-M router and its opt-in dispatch.
@Jiminator

Jiminator commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator Author

@BBuf
BBuf merged commit 7c9a78e into main Oct 19, 2026
122 of 190 checks passed
@BBuf
BBuf deleted the nemotron3-super-dev-20261015 branch October 19, 2026 05:27
brandonfzhang added a commit to brandonfzhang/sglang that referenced this pull request Oct 19, 2026
Conflict: main's sgl-project#44518 added an opt-in host-indptr draft plan that reuses
the token-block launch with 512-token blocks (<=32). Resolved to one launch
sized by spec_kv_index_token_blocks, never below the host-plan path's
tiling, and a single NUM_STEPS kwarg covering both triggers. main absorbed
the kernel-side token-block support, so this branch now carries only the
sizing helper, call-site wiring, and tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
detain pushed a commit to detain/sglang that referenced this pull request Oct 29, 2026
…project#44901)

cherry-pick -x 3a059de. PORT ORDER: landed FIRST in this family because
its merged mainline chronology makes it the strict precondition of sgl-project#44904
(main merges: sgl-project#44901 16:54 -> sgl-project#44904 16:56 -> sgl-project#44912 16:57 -> sgl-project#44913 16:59;
sgl-project#44904's diff preimage literally consumes fused_shared_expert_weight /
is_routed_scaling_factor_fused_in_topk introduced here, and sgl-project#44913's preimage
deletes the helpers sgl-project#44912 introduces -- the only cherry-pickable order is the
mainline one; later commits in this family build on earlier ones).

Conflict resolutions (2):
  * models/deepseek_v2.py: the pick's hunk anchors on `class
    MergedMoEOutput(MoEOutput)` as CONTEXT, but that class is upstream
    sgl-project#44657 content this fork never took (review-record skip family), so the
    region conflicted empty-vs-context. Kept ONLY sgl-project#44901's own addition:
    _scale_routed_and_add_shared (verified byte-identical to the upstream
    post-image function text) plus all nine routed_scaling_factor_fused_in_topk
    sites (two __init__ sets, the aiter shared-scaling compensation block,
    two non-CUDA post-MoE-multiply guards, and the forward_deepep/state-based
    forward replacements). Nothing in this tree references MergedMoEOutput;
    did not smuggle it in.
  * test/registered/unit/layers/moe/test_mega_moe_decode_capacity.py:
    modify/delete conflict (the file was created by sgl-project#44657, absent here;
    sgl-project#44901 merely touched 1 line inside it). Kept it deleted.

Fidelity: 7/12 python files are BYTE-IDENTICAL to the upstream post-image
(topk.py, hash_topk.py, waterfill.py, moe_ep_setup.py, glm4_moe.py,
glm4_moe_lite.py, vl_routing.py). mega_moe/mega_moe_flydsl/bailing_moe_v3/
dots3 landed inside files carrying nemotron-era (sgl-project#44518) upstream drift we do
not have; their fold changes were diff-reviewed line by line (old
`should_fuse_routed_scaling_factor_in_topk or _use_aiter` predicates replaced
by the new config-level predicate; residual old-form reads match upstream's
own post-image -- legitimately kept). WaterfillBalancer's routed_scaling_factor
kwarg became shared_weight (one production constructor, moe_ep_setup, updated
by the pick; no other call sites in the tree).

Battery (CVD=9) vs base 0df18e9: test_fused_shared_expert_scaling.py
6P -> 12P/25sub (upstream's +343-line fold matrix, green); test_hash_topk.py
3P -> 4P; test_jit_grouped_topk 10S -> 12S (CUDA-gated adds); every pin held
(standard_dispatcher_runner_backend 12P, smallm 28P/66sub, b12x 67P/46sub,
kernels_namespace 76P, model_overrides 111P/1S/179sub, modelopt suites exact).
Pre-existing classes unchanged (trtllm-gen 8F, fused_gate 46F, round-robin 37F,
triton-fused-moe 96F, mem_pool_ep 1F, mega_moe_deepgemm 1F).
ruff --select=F401,F821,F823,UP037 + ruff format clean on all 18 files.

Fold-predicate e2e on real NVFP4 weights stays GPU-window debt (the standalone
CPU contract probe follows this family as its own commit).

(cherry picked from commit 3a059de)

Co-authored-by: port-moe-contracts subagent
(cherry picked from commit c4511d515077ea018200eeccfff256cc25ff18e5)
detain pushed a commit to detain/sglang that referenced this pull request Oct 29, 2026
…ts only (sgl-project#44904)

cherry-pick -x 48ea486. Landed second of the renorm pair: mainline makes
sgl-project#44904 build ON TOP of sgl-project#44901 (its diff preimage contains fused_shared_
expert_weight/is_routed_scaling_factor_fused_in_topk), so the family follows
the mainline order (see sgl-project#44901's note here).

Wrong-output class: before this, the fused per-rank shared-slot paths asked
the gate for top_k while num_fused_shared_experts markers also went through,
renormalizing over one routed expert too many (routed sum 0.85-0.97 on CUDA).

Conflict resolution (1): test/registered/kernels/ops/moe/test_moe_fused_gate.py
carries pre-sgl-project#44690 docstring drift here (this fork never took sgl-project#44518's
nemotron rework of that file's header); took the upstream post-image's new
one-line docstring, kept this fork's file otherwise. The _reference_gate
renorm-order fix, the renorm x apply_scale parametrization, and the
production-impl comparison changes all landed.

Fidelity: topk.py, hash_topk.py, state_capturer/routed_experts.py,
test_fused_append_remap_per_rank_shared_slots.py and
test_fused_shared_expert_scaling.py are BYTE-IDENTICAL to the upstream
post-image; _router_triton_kernel (kernels/ops/moe/moe_fused_gate.py) verified
byte-identical function body against upstream (the file's OTHER regions carry
this fork's jit-loader drift and were not touched); fused_moe_triton_kernels.py
hunks are docstring-only.

Battery (CVD=9) vs sgl-project#44901 commit: test_fused_shared_expert_scaling 12P ->
13P/25sub; waterfill_eplb 4P -> 5P; scattered_a2a 3P -> 5P/2sub (the new
routed-width capture case); hash_topk 4P held; append 6S -> 9S, padded 10S ->
11S (CUDA-gated adds); moe_fused_gate 46F -> 52F = the file's pre-existing
no-CUDA class +6 new parametrized members (collects clean; needs hardware);
kernels_namespace 76P (inventory guard, nothing added/removed); every other
pin exact. ruff + format clean on all 11 files.

Remap-on-CUDA numerics (torch.cat width change + padded-row remask) remain
GPU-window debt, pinned at contract level by the fold-predicate probe commit
that follows.

(cherry picked from commit 48ea486)

Co-authored-by: port-moe-contracts subagent
(cherry picked from commit 0432a8fce0b4919b4a85fc6d3e724c6de30189be)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

apple-silicon blackwell SM100/SM120 jit-kernel lora quant LLM Quantization 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.

3 participants