Skip to content

[Fix] moe: Renormalize per-rank shared-slot routing over routed experts only - #44904

Merged
ch-wan merged 1 commit into
mainfrom
cheng/hot-fix/per-rank-shared-slot-topk
Oct 19, 2026
Merged

ch-wan merged 1 commit into
mainfrom
cheng/hot-fix/per-rank-shared-slot-topk

Conversation

@ch-wan

@ch-wan ch-wan commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

This PR is part of a stack (oldest at bottom):

Motivation

With fused shared experts in per-rank slots (--enforce-shared-experts-fusion with a DeepEP-class or megamoe a2a backend), every MoE layer renormalized its routed weights over one routed expert too many on CUDA, so the routed experts it kept summed to about 0.85-0.97 instead of 1.0.

How it happened:

  1. On the per-rank slot path select_experts gives the router no shared slot (num_fused_shared_experts=0), because _post_process_topk_ids appends the shared column afterwards. On aiter it also gives the router the routed count, top_k - num_fused_shared_experts. Off aiter every router call kept top_k (num_routed_topk if _use_aiter else top_k), which counts the shared slot.
  2. So the router selected top_k routed experts, one more than the model's num_experts_per_tok, and renormalized their weights to sum to 1.
  3. remap_topk_for_per_rank_shared_slots then overwrote the last column with the home-rank shared expert.
  4. The routed experts kept sum to sum(top K) / sum(top K+1), per token, in every layer. The CUDA routers return their top-k sorted by score, so the kept experts are the right ones; only their weights shrink.

#36515 (non-grouped routers) and #40943 (grouped routers) gave the router 0 shared slots on this path. That fixed aiter, where the router already gets the routed count, and left CUDA in the state above. Before them, CUDA gave the router top_k with the shared slot, which selects the routed count and renormalizes over it.

Kept routed weight sum per token, one H200, 64 tokens of random logits, EP8, rank 3, one shared expert:

Router path Before After
grouped sigmoid + bias, 256 experts, top-8 (DeepSeek-V3 shape; FlashInfer router after the fix, Triton fallback before) 0.873-0.913 1.0000
grouped sigmoid + bias, 384 experts in 8 groups, top-8 0.873-0.914 1.0000
grouped, one group, sigmoid + bias, 384 experts, top-8 (Kimi-K2 shape) 0.873-0.919 1.0000
grouped softmax, no bias, 64 experts, top-6 0.886-0.967 1.0000
ungrouped sqrtsoftplus + bias, 256 experts, top-6 (DeepSeek-V4) 0.850-0.885 1.0000
ungrouped sigmoid + bias, 256 experts, top-8 0.877-0.912 1.0000
ungrouped softmax, 128 experts, top-8 0.909-0.949 1.0000
HashTopK (DeepSeek-V4 hash layers), torch and fused kernel 1.0000 1.0000
DeepSeek-V4.1 vision routing on MegaMoE 1.0000 1.0000

In every row the routed experts equal routing without fusion (64/64 rows) before and after; the shared column is the home-rank slot with weight 1/routed_scaling_factor.

Affected: CUDA, and other platforms without aiter, with shared-experts fusion on a per-rank backend (deepep, mooncake, mori, pplx, megamoe); for the DeepSeek family that takes --enforce-shared-experts-fusion. The original per-rank normalization bug does not affect aiter, Waterfill, the global fused slot (no a2a backend), runs without fusion, HashTopK and the DeepSeek-V4.1 vision routing, whose routers already select the routed experts alone.

Two related problems on the same path are fixed here too:

  • FlashInfer's DeepSeek router ignores renormalize. fused_topk_deepseek always normalizes the selected weights, and its ninth parameter is launch_with_pdl, which sglang's wrapper called renormalize. With routed-only sizing the per-rank top-8 path now fits that router (top-9 did not), so a renormalize=False configuration would have been normalized. Configurations without fusion or with the global slot already were, within that router's shapes. Grouped sigmoid routing with a bias, 256 experts in 8 groups, top-8, renormalize=False, zero logits (each raw weight is sigmoid(0) = 0.5): before this PR 0.125 per expert without fusion and 0.5 with a per-rank slot; with this PR's first version 0.125 for both; now 0.5 for both.
  • Padded rows on the per-rank path. The append shifted a padded row's -1 to -1 - num_fused_shared_experts and gave it a live home-rank shared slot, so padded rows did not leave top-k as -1. HashTopK and the vision routing already mask after their append.

The renormalize=False guard also exposes the Triton global shared-slot path. That path previously wrote sum(selected routed scores) / rsf before normalization, so disabling normalization made the shared output depend on the routed-score sum (4x for eight zero-logit sigmoid selections). It now writes a shared weight of 1 when rsf is folded, otherwise 1/rsf, after processing the routed weights. The dynamic-bias torch route receives the corresponding repair from #44901.

Modifications

  • select_experts decides once, for every router, what the router is asked for: where _post_process_topk_ids appends the shared columns (aiter, per-rank slots), the routed count with no shared slot; otherwise top_k with the shared slots, as before. The values are unchanged on aiter, on the global slot and without fusion.
  • remap_topk_for_per_rank_shared_slots takes the routed columns and appends the shared ones, the contract fused_append_remap_shared_experts_deepep already has on aiter. Routers that still write shared placeholders (the per-token-bias router, the DeepSeek-V4.1 vision routing, HashTopK) have them dropped before the append. On CUDA the EPLB remap splits off shared columns only when the router wrote them, and padded rows are masked again after the append.
  • biased_grouped_topk_gpu takes the FlashInfer branch only when renormalizing; otherwise the Triton router, which honors renormalize, serves the call. The wrapper's last parameter is renamed launch_with_pdl, and the global shared columns that branch appends take fused_shared_expert_weight(...).
  • RoutedExpertsCapturer.capture pads routed-only ids (the device width minus the fused shared experts) to its device width and raises on any other width; the host side already keeps only num_experts_per_tok columns. The per-rank path now captures routed-only ids, and without the pad --enable-return-routed-experts would fail with a shape mismatch.
  • The fused aiter kernel's docstrings name its eager twin.

Tests

On one H200 (driver 595.71.05, torch 2.14.1+cu130, flashinfer 0.7.2, triton 3.8.0), for this branch (03d13ebf8b), its base #44901 (bd4de12cfa) and this PR's previous head merged with that base:

  • test/registered/unit/layers/moe/test_fused_shared_expert_scaling.py::test_per_rank_slot_routes_like_no_fusion (CPU): select_experts with a per-rank slot keeps the routed experts and weights of routing without fusion, summing to 1. Fails on the base, passes here.
  • test/registered/moe/test_fused_append_remap_per_rank_shared_slots.py (CUDA):
    • TestSelectExpertsPerRankSharedSlots::test_routes_like_no_fusion: the same property through five CUDA routers (the DeepSeek-V3 grouped router, the Triton grouped fallback, torch grouped routing, the DeepSeek-V4 sqrtsoftplus router, softmax). Fails on the base for all five, passes here.
    • test_unnormalized_weights_stay_raw: with renormalize=False the routed weights equal the raw sigmoid scores of the reference selection, with and without a per-rank slot. Fails on the previous head (both cases) and on the base (without fusion), passes here.
  • test/registered/moe/test_topk_padded_region.py::TestSelectExpertsPerRankSharedSlotPadMask (CUDA): padded rows leave the per-rank path fully -1, for a router masked after routing and one that masks itself. Fails on the base and on the previous head, passes here.
  • test/registered/unit/eplb/test_waterfill_eplb.py::test_eplb_remaps_every_column_of_routed_only_per_rank_ids (CPU): EPLB remaps every routed column of routed-only per-rank ids, and the recorder sees them. Fails on the base, passes here.
  • test/registered/unit/state_capturer/test_routed_experts_scattered_a2a.py::TestCaptureRoutedIdsOnly (CPU): routed-only ids land in the routed columns, with and without the DeepEP gather; any other width raises. Fails on the base (shape RuntimeError) and, for the rejection case, on the previous head; passes here.
  • The remap cases in test_fused_shared_expert_scaling.py and the kernel/eager equivalence case pass routed-only columns.
  • The MoE, DeepSeek, EPLB and state-capturer unit files (test/registered/unit/layers/moe/, unit/models/test_deepseek_*.py, unit/models/test_shared_experts_fusion_gates.py, unit/eplb/, unit/state_capturer/, moe/test_hash_topk.py) plus the GPU routing tests (moe/test_topk_padded_region.py, moe/test_topk_renormalize_degenerate.py, kernels/ops/moe/test_jit_grouped_topk.py, kernels/ops/moe/test_moe_fused_gate.py, kernels/ops/moe/test_round_robin_ep_balance.py, moe/test_fused_append_remap_per_rank_shared_slots.py): 55 files, each in its own process, CPU-registered ones with the GPUs hidden. All pass on the base and on this branch.
  • The tables above: select_experts, HashTopK and vision_topk with the real kernels, on the base, the previous head and this branch.

Additional validation at 4676743e28 (one H200, same library versions):

  • The integrated scaling file passes all 13 CPU tests; the append/remap and runtime-routing file passes all nine CUDA tests.
  • The new global renormalize=False regression fails against the previous production code for both folding modes (4x shared coefficient) and passes after the kernel repair.
  • The fused-gate reference suite passes all 39 cases; the degenerate routing file passes all seven cases. The reference writes the shared coefficient independently after routed normalization/scaling.
  • Applicable pre-commit hooks pass.

Owed

  • A GPU accuracy eval on an affected configuration, before and after: for example DeepSeek-V3 with --moe-a2a-backend deepep --enforce-shared-experts-fusion, or DeepSeek-V4 on MegaMoE (SM100). Not run.
  • ROCm: not run. The aiter paths give the router the same arguments as before (code reading).

CI fixture follow-up at beb15ea999

The ROCm 10 MI35x job failed at faaf4bb4e6 because test_deepseek_v4_amd_tp4.py::_moe_stub bypasses DeepseekV2MoE.__init__ and omitted routed_scaling_factor_fused_in_topk. The stub now supplies that construction state. The other five test files in that partition passed. This fixes the test fixture; production executable behavior is unchanged.

On one H200, the original fixture reproduces the same AttributeError with the AITER epilogue flags forced; after repair, all four normal/dual-stream and shared-TP1 combinations pass through the actual forward methods. This checks the Python fixture/epilogue contract, not native ROCm collectives or graph replay. The complete AMD TP4 file still needs CI validation.

The kernel comparison now covers normalization and explicit folding independently; the complete standalone router test file passes all 52 cases on one H200. Its stale normalization explanation and CUDA JIT parity claim are corrected. The CUDA counterpart retains its existing unnormalized shared-weight behavior; caller search found tests and benchmarks, with no serving caller.

TopKConfig documents its total ordinary output width and the global AITER absolute shared coefficient versus the standard-path multiplier. Eager/fused subtest labels include the folding mode. Duplicate ordinary model-context scopes and a derived routed-count property remain optional follow-ups. Applicable pre-commit hooks pass. No native AMD rerun or model accuracy result is claimed for this follow-up.

Landing cleanup (2026-10-19)

Current head: 39bdf12a49, rebased onto main after #44901 merged.

Trimmed repetitive comments and docstrings. Configured cleanup checks passed before landing. Rebase resolution keeps main's removal of obsolete CUDA-JIT comparison prose and preserves routed-only append behavior, including empty output widths. Earlier test results above retain their original revisions; no new accelerator or full-model run is claimed for this cleanup/rebase.

The broader routing matrix moves to opt-in Extra coverage in #44913; the focused CPU and append/remap regressions remain on the normal path.


CI States

Latest PR Test (Base): ❌ Run #39344592460
Latest PR Test (Extra): 🚫 Run #39344592427
Latest PR Test (AMD ROCm 10): ❌ Run #39344592456

@ch-wan
ch-wan force-pushed the cheng/hot-fix/per-rank-shared-slot-topk branch from beb15ea to 39bdf12 Compare October 19, 2026 23:56
@ch-wan
ch-wan merged commit 48ea486 into main Oct 19, 2026
36 of 47 checks passed
@ch-wan
ch-wan deleted the cheng/hot-fix/per-rank-shared-slot-topk branch October 19, 2026 23:56
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)
detain added a commit to detain/sglang that referenced this pull request Oct 29, 2026
…lass NVFP4 route

Standalone CPU contract test pinning WHAT WE NOW BELIEVE after the two
fold fixes (sgl-project#44901 + sgl-project#44904) land on our production FP4 arm --
ModelOptNvFp4FusedMoEMethod on a FLASHINFER_CUTLASS runner, the backend
auto resolves to on SM110/SM120 (and the value entry 230's fork patch
publishes for it):

  * FusedMoE._fuses_routed_scaling_factor_in_topk answers True for NVFP4
    on every non-Marlin runner (and False on Marlin) -- the predicate
    list sgl-project#44901's shared-slot fix keys off; no NVFP4 class-level
    fuse_routed_scaling_factor_in_topk flag exists, so the verdict comes
    from the runner arm.
  * topk.is_routed_scaling_factor_fused_in_topk (sgl-project#44901) agrees via
    apply_routed_scaling_factor_on_output.
  * topk.fused_shared_expert_weight (sgl-project#44901) therefore writes the fused
    shared column 1.0 -- not 1/routed_scaling_factor -- exactly where
    sgl-project#44904 moved the kernel/append fill to AFTER routed renormalization.

8 passed here (import/config level only, register_cpu_ci base-a-test-cpu).
Red proof of newness: is_routed_scaling_factor_fused_in_topk and
fused_shared_expert_weight do not exist at the port base (0df18e9),
so the import alone fails pre-pick -- this file cannot pass without
sgl-project#44901/sgl-project#44904 landed.

GPU-WINDOW DEBT, explicitly NOT covered here: the end-to-end
double-scale numeric check (generate against a single-scale reference on
4xSM120 with the real checkpoint; sgl-project#44901's routed-sum 0.85-0.97 symptom
and the shared-contribution 1.0x property only OBSERVABLE on hardware).
Test-side of the same property: kernels/ops/moe/test_moe_fused_gate.py's
new renorm x apply_scale parametrizations are CUDA-gated (52F here, the
file's pre-existing device class at base was 46F -- same class, +6 new).

Co-authored-by: port-moe-contracts subagent
(cherry picked from commit 22ae8e7e609fce945cdc85d3f985a253cfba1aa2)
detain pushed a commit to detain/sglang that referenced this pull request Oct 29, 2026
…gl-project#44912)

cherry-pick -x 964ab2b. Applies CLEANLY (zero conflicts): the fork never
edited topk.py/hash_topk.py since merge sgl-project#4, and sgl-project#44901/sgl-project#44904's post-images
(landed in the two preceding commits) exactly reconstruct upstream's preimage
at the touched lines.

Semantics: TopKConfig.num_fused_shared_experts (the count of fused shared
experts) splits into num_shared_topk_slots (the trailing columns the ROUTER
writes -- zero when Waterfill appends the shared expert after routing), and
TopK.__init__ now derives top_k for the config as routed-per-token + slots
instead of mutating the caller's numbers. New helpers waterfill_
routes_shared_experts / shared_topk_slots live in moe/utils.py; the
enable_waterfill branch stops silently redefining top_k (waterfill now forces
STANDARD output format explicitly).

Entry-247 interaction preserved: b12x's _keeps_global_expert_ids and the
slot-count vocabulary this family touched before were not in sgl-project#44912's hunk
regions; moe/utils.py post-image differs from upstream ONLY by the 7 b12x
enum/predicate lines already in the tree (git diff vs 964ab2b: +7/-0),
so the split landed upstream-identical and test_b12x_w4a16_route stayed
67P/46sub unchanged.

test_manual NPU file (test_npu_topk.py) took the 1-line rename too (hardware_
backend/npu/moe/topk.py likewise); NPU paths are inert here.

Battery (CVD=9) vs sgl-project#44904: waterfill_eplb 5P -> 6P/2sub (upstream's new
waterfill slot case); everything else byte-stable (scaling 13P/25sub, hash 4P,
append 9S, padded 11S, jit 12S, smallm 28P/66sub, dispatcher 12P, b12x
67P/46sub, kernels_namespace 76P, trtllm-gen 8F class). ruff + format clean.

NUM_SHARED_TOPK_SLOT wiring at runtime (per-rank append widths on real
dispatch) stays GPU-window debt, same as the renorm pair above.

(cherry picked from commit 964ab2b)

Co-authored-by: port-moe-contracts subagent
(cherry picked from commit ad00ea48739c10c0345f572bed8d8aad818c0169)
detain added a commit to detain/sglang that referenced this pull request Oct 30, 2026
…ies 28,165,166,186,194,206,296,297,299,300

PER-MARKER TRUTH (census: B5 markers in this set now ZERO):
  kernels/aot topk.cu (28): VERIFIED-ABSORBED -- upstream's in-range
  legacy_radix_topk::select rewrite gates the threshold-bin population
  against the stash BEFORE staging (coarse_population >= StashEntries ->
  full-row byte-per-pass refinement), structurally fixing the overflow
  the fork patched after-the-fact; jit twin keeps its s_prefix_bins.
  kernels/ops/attention/utils.py (194): VERIFIED-ABSORBED -- the function
  re-sited to ops/attention/kv_indices.py (spec_kv_index_token_blocks with
  the 32768 gate) and every consumer imports it at that module; the saved
  utils re-export would be a dead hunk (zero importers).
  elementwise/elementwise.py (166): VERIFIED-PRESENT -- the batch-invariant
  num_warps clamp rides upstream's guard_or_false refactor ('or
  is_batch_invariant_mode_enabled()' intact).
  kvcache/__init__.py (186): VERIFIED-PRESENT -- the store_cache_fp8
  registry entry is the merge commit's own graft (entry 310), imports +
  capabilities in place.
  moe/hash_topk.py + moe/topk.py (296/297/299/300): the merged upstream
  canonicals of sgl-project#44901/sgl-project#44904/sgl-project#44912/sgl-project#44913 are IN RANGE (all four
  MERGED commits proven ancestors of 2a6c204); every fork symbol
  (fused_shared_expert_weight, is_routed_scaling_factor_fused_in_topk,
  num_shared_topk_slots x54, has_per_rank_fused_shared_slots,
  SharedExpertsConfig wiring) verified present. Markers stale.
  moe/flashinfer_trtllm.py (165): SUPERSEDED-BY-EQUIVALENT -- upstream's
  own in-range rewrite of the deferred block covers the routed triple
  (do_finalize=not defer + _make_deferred_finalize_output) fail-LOUDER
  (valid_deferred_input raise); the fork's sgl-project#6077 ignored-autotune-buffer
  targeted the OLD block shape and is deliberately NOT restored (GPU
  perf-only, defer+routed is not our production arm).
  moe/mega_moe.py (296): deep_gemm transform_sf redirect RE-PLANTED to the
  guarded wrapper (import-safety contract; sibling fix in dsv4 below).
  fused_moe_triton/layer.py (165/206/239): _built_runner_backend hunk
  ABSORBED by sgl-project#44993 (config carries the built runner); the entry-206
  supports_routed_deferred_finalize property RE-PLANTED (upstream's
  packed_nvfp4_routed_deferred covers TRTLLM only, NOT trtllm_routed --
  our runner arm), with the sgl-project#44993 2-arg fold predicate; the debug-log OR
  re-plant paired.
  models/deepseek_v2.py (296/297/300/236): fold chain verified; the
  entry-206 format-ternary consumer arm RE-PLANTED (BYPASSED ->
  supports_deferred_finalize, else supports_routed_deferred_finalize --
  restoring what sgl-project#44993's rewrite dropped).

Battery ACTUALS (CVD=9, prod venv, PYTHONPATH=python, import sglang OK):
  fused_shared_expert_scaling + mega_moe_deepgemm_api + moe_runner_
  extensions + topk_routing_inputs + model_overrides + kernels_namespace:
  GREEN (see B5-4 commit for full 43-file battery actuals)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant