Skip to content

[CUDA] Update MoEGroupRouter for routing to MoEPacked - #33994

Merged
Tianlei Wu (tianleiwu) merged 13 commits into
rui-ren/bolt-mamba-on-33963-20261107from
rui-ren/bolt-standalone-router-on-33969-20261108
Nov 12, 2026
Merged

Tianlei Wu (tianleiwu) merged 13 commits into
rui-ren/bolt-mamba-on-33963-20261107from
rui-ren/bolt-standalone-router-on-33969-20261108

Conversation

@rui-ren

@rui-ren Rui Ren (rui-ren) commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Description

Keep the existing CPU/CUDA com.microsoft::MoEGroupRouter and its legacy dense
output 0 unchanged. Optional dense projection weights remain unquantized
FP32/FP16/BF16 tensors.

The routing interface now exposes only the full arrays consumed by native MoE:

Output Name Type / shape
0 router_probs Legacy activation-dtype log-scores, optional
1 selection_scores FP32 [tokens, experts]: sigmoid plus correction bias
2 router_weights FP32 [tokens, experts]: unbiased sigmoid

Outputs 1/2 must be requested together, with output 0 omitted. The unused compact
expert_indices / expert_weights outputs, Tind, router_scale, and compact
CPU/CUDA routing implementation are removed. Full-score outputs move from 3/4
to 1/2. Full-score mode requires one group, at most 512 experts and
rows <= INT_MAX; projection requires rank-2 activations and a positive width
divisible by 256.

Graph wiring: MoEGroupRouter([router_input, correction_bias, dense_weight], outputs=["", selection_scores, router_weights], top_k=k).
Connect selection_scores to MoEPacked's router_probs input and the unbiased
array to its router_weights input. MoEPacked performs top-k selection and
selected-weight normalization; apply model routing scale explicitly in the
composed graph. The chained regression retains an external Mul(2.5).

Legacy dense routing and full-score sigmoid/projection arithmetic are unchanged.
This layer does not change QMoE or MoEPacked's schema/packed payload.
Dependency: #33969 in native stack #33967.

Current focused qualification

Owning head: c57ef4627f28ab8bf3dce260ffc382a25c26e299.
Synchronized descendants: #34002 99d57c485bdac723f1f2c646bf239fc4e35e3f70,
#34003 ea71ed9e9070ce15b630eaa24dae3277f0a06cb7. Their individual net changes are preserved exactly;
all eight original stack members and the lower PR heads are retained.

  • 25 production router/shape/projection tests plus one native metadata/factory
    guard passed, zero failures or skips, at both the owning and synchronized top
    layer. FP32, FP16 and BF16 execute on the intended CPU/CUDA paths.
  • Each run profiles 56 CPU router executions, 113 CUDA router executions and four
    CUDA MoEPacked executions. The chained FP16/BF16 tests retain the unchanged
    numerical thresholds and external model-scale operation.
  • Changed native router/consumer CUDA sources, CPU kernels, schemas and tests
    were compiled against retained ORT support libraries. This is not a clean
    full-source build or full-CI acceptance
    .
  • ContribOperators.md and CPU/CUDA OperatorKernels.md router sections are
    regenerated and checked with the official renderers using fresh native
    schema/kernel metadata. Stripped text is restored from the executing schema
    source. Unrelated sections are preserved. Full --gen_doc validate is NOT_RUN.
  • Changed-range clang-format and whitespace checks pass. No full-model,
    speculative-integration or performance acceptance is claimed by this update.

Local immutable qualification receipts, source snapshots, binary hashes and
provider profiles:
/root/.copilot/session-state/3b29a5de-77c7-4cf5-b77a-02adf4f73c89/files/pr33994-remove-compact-routing.

Historical PR description and earlier-head evidence (not current-head acceptance)

Description

Extends the existing CPU and CUDA com.microsoft::MoEGroupRouter with optional dense router projection and two ways to expose routing results. The existing grouped dense-logit path and router_probs output remain available. No separate router operator is introduced, and this PR does not change QMoE.

With projection_weight, the operator computes router logits from rank-2 activations and ordinary dense, unquantized weights. It can expose either:

  • Compact routing: paired expert_indices and expert_weights outputs. Selection uses sigmoid scores plus expert_bias; the returned weights use the unbiased sigmoid scores, with optional normalization and router_scale. This mode is currently restricted to n_group=topk_group=1, at most 512 experts, and top_k <= 32.
  • Full-score routing: paired FP32 selection_scores and router_weights outputs. router_weights contains unbiased sigmoid values; selection_scores contains those values plus expert_bias. This mode does not select top-k, normalize, scale, mask, or take logarithms. A downstream operator performs selection and weighting; the full-score outputs compose with MoEPacked from [CUDA] Extend MoEPacked for top-k, dispatch and fused MoE calculation #33963.

The compact outputs remain exposed by this PR, but currently have no in-tree consumer. The MoEPacked composition uses the full-score outputs.

Tests cover CPU and CUDA routing, projection and shape inference, tie-breaking, selection bias versus mixing weights, boundary and invalid-input cases, and a chained full-score MoEPacked reference comparison.

Motivation and Context

Keep router computation reusable and separate from expert execution. The optional projection lets MoEGroupRouter own the router arithmetic, while its full-score interface allows MoEPacked to select experts and execute packed experts without adding a learned router projection to MoEPacked.

This PR preserves the existing MoEGroupRouter schema and dense-logit behavior while adding optional outputs and projection support. It does not modify QMoE.

@rui-ren
Rui Ren (rui-ren) marked this pull request as ready for review November 9, 2026 18:19
Copilot AI balanced review requested due to automatic review settings November 9, 2026 18:19
@rui-ren
Rui Ren (rui-ren) force-pushed the rui-ren/bolt-standalone-router-on-33969-20261108 branch from a8ff564 to 973d161 Compare November 9, 2026 18:25
Copilot stopped reviewing on behalf of Rui Ren (rui-ren) due to an error November 9, 2026 18:25
@rui-ren
Rui Ren (rui-ren) force-pushed the rui-ren/bolt-standalone-router-on-33969-20261108 branch from 973d161 to ebdbb85 Compare November 9, 2026 18:34

Copilot AI 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.

Note

Copilot was unable to run its full agentic suite in this review.

Copilot review overview

3 open issues
What changed in this PR

Adds a new CUDA contrib operator MoERouterPacked to provide projected-sigmoid routing for MoEPacked, including schema/registration, shared CUDA implementation, tests, and documentation updates.

Changes:

  • Introduce MoERouterPacked operator schema and CUDA kernel registration.
  • Implement routing CUDA kernels (sigmoid scoring + deterministic top-k) and refactor MoEPacked sigmoid-routing path to reuse them.
  • Add CUDA-focused unit tests and update operator documentation.
File Description
onnxruntime/​test/​contrib_ops/​moe_router_packed_test.cc Adds CUDA tests for routing behavior, tie-breaking, edge cases, and validation.
onnxruntime/​core/​graph/​contrib_ops/​ms_opset.h Registers the new operator schema in the Microsoft opset.
onnxruntime/​core/​graph/​contrib_ops/​contrib_defs.cc Defines the MoERouterPacked operator schema, constraints, and documentation.
onnxruntime/​contrib_ops/​cuda/​moe/​moe_router_packed_impl.h Declares shared CUDA launcher and packed-load helper.
onnxruntime/​contrib_ops/​cuda/​moe/​moe_router_packed_impl.cu Implements sigmoid projection and deterministic top-k selection CUDA kernels.
onnxruntime/​contrib_ops/​cuda/​moe/​moe_router_packed.h Declares the CUDA kernel wrapper class for the new op.
onnxruntime/​contrib_ops/​cuda/​moe/​moe_router_packed.cc Implements kernel validation, scratch allocation, and launch wiring.
onnxruntime/​contrib_ops/​cuda/​moe/​moe_packed.cu Refactors existing sigmoid-routing to call the shared router launcher; reuses packed-load helper.
onnxruntime/​contrib_ops/​cuda/​cuda_contrib_kernels.cc Registers MoERouterPacked CUDA kernels for FP16/BF16.
docs/​OperatorKernels.md Documents kernel availability/signature for MoERouterPacked.
docs/​ContribOperators.md Adds generated operator documentation section for MoERouterPacked.

Review effort: Lite

@rui-ren Rui Ren (rui-ren) left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Stack #33967 review — parent 5809f2531dcb -> head ebdbb8548801.

Reviewed the standalone schema/kernel registration, FP16/BF16 projection, selection-only bias, finite/exceptional ranking and lower-ID ties, selected-rank FP32 normalization, and the integrated MoEPacked call into the same shared implementation. No new actionable correctness finding in this extraction.

The current byte-scratch alignment comment is not a demonstrated defect: GetScratchBuffer delegates to the same CUDA allocator, and changing T changes the allocation's count units, not its alignment. The normal CUDAAllocator uses cudaMalloc; the arena preserves allocator alignment. A typed float scratch buffer can improve clarity, but it does not itself repair an alignment failure. Likewise, naming the inherited 1e-20f stabilizer may clarify intent, but preserve its value and normalization order when doing so.

This is static review feedback, not a new clean build, standalone-op runtime test, or approval of outstanding CI.

@tianleiwu Tianlei Wu (tianleiwu) 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.

Reviewed this layer (stack #33967, layer 4) at ebdbb85488.

Extraction fidelity. I diffed the removed MoEPackedSigmoid* kernels in moe_packed.cu against moe_router_packed_impl.cu after renames: kernel bodies, launch geometry and error checks are identical, and MoEPacked now goes through the shared LaunchMoERouterPackedCuda. I also ran the unmodified kernels on an H200 against an independent host reference (1,200 randomized FP16/BF16 cases with ties, +/-inf and NaN bias and activations, 16-byte-misaligned pointers, widths 256-2048, experts 1-512, k 1-32) and found no selection or weight mismatches. Schema, kernel registration and op-set registration look correct.

No blocking issues. Main requests (all inline):

  1. The new tests use all-zero (or single-element) data, so common kernel regressions still pass them.
  2. The ContribOperators.md entry cannot be regenerated from the schema; doc-gen validation will report a diff once this PR targets main.
  3. Smaller API-robustness items: a lumped validation message and missing shape inference.

Non-blocking design notes

  • The standalone op rejects rows > 2048, while MoEPacked chunks internally at 2048 rows, so a graph that swaps in MoERouterPacked must pre-chunk long prefills itself. If that is intentional, say "callers must chunk" in the schema text and pin it with a rows = 2049 rejection test; otherwise the same chunk loop can be used here, since the kernels have no row limit other than grid.x (the cap only bounds the FP32 score scratch).
  • LaunchMoERouterPackedCuda is now a shared entry point whose memory-safety preconditions (width % 256 == 0, experts <= 512, 1 <= k <= min(32, experts)) are enforced only by its callers (moe_router_packed.cc for the op, DispatchMoEPackedCuda and moe_packed.cc for the integrated path). A host-side guard in the launcher is cheap and keeps the two call sites from drifting.
  • The BF16 SM80 check runs in ComputeInternal on every Run(), whereas MoEPacked enforces it in the constructor, so an unsupported device fails at the first inference rather than at session creation.

On the existing Copilot comments: I agree the scratch-alignment concern is not a defect (same allocator, and arena chunks are 256-byte aligned); the <cmath> and epsilon-naming items are optional.

Comment thread docs/ContribOperators.md Resolved
@rui-ren
Rui Ren (rui-ren) force-pushed the rui-ren/bolt-standalone-router-on-33969-20261108 branch from ebdbb85 to 6c1fc43 Compare November 9, 2026 23:43
@rui-ren Rui Ren (rui-ren) changed the title [CUDA] Extract Bolt projected-sigmoid routing into MoERouterPacked Reuse MoEGroupRouter for projected sigmoid routing Nov 10, 2026
@rui-ren

Copy link
Copy Markdown
Contributor Author

Updated in c7f2ea8 to reuse the existing CPU/CUDA MoEGroupRouter from #33817, with optional ordinary dense projection and compact IDs/FP32 weights. Router weights are not quantized; MoERouterPacked is removed and the legacy grouped interface remains supported.

Fresh source-built validation passed 40 provider/schema tests, all six native GenAI capture/state tests (including R1/R8), 36 real component cases and 240 same-mode generation checks. The audited seven-H100 1k/2k/8k TTFT/TPS table is in the updated description; observed decode overhead versus integrated routing is 0.28–0.51% in this small sample. These rates are for this layer, not the downstream performance-stack tip.

Coordination: #34002/#34003 branches and the complete native stack membership are untouched. Please synchronize those active downstream layers with the updated parent before combined-stack qualification; I have not force-rebased or merged them.

@rui-ren
Rui Ren (rui-ren) force-pushed the rui-ren/bolt-standalone-router-on-33969-20261108 branch from c7f2ea8 to 74a7e07 Compare November 10, 2026 00:40

@tianleiwu Tianlei Wu (tianleiwu) 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.

Re-review of 232a1dfa59.

Verdict: COMMENT — but two compile errors introduced in this layer must be fixed before merge: they break the Windows CUDA and wasm32 builds, and #34002 / #34003 inherit them.

The standalone MoERouterPacked op from the previous revision is gone, so my earlier threads on it are moot. Their equivalents on the new code are in place: observed-value diagnostics in ValidateMoEGroupRouterProjection, shape inference that validates every known operand, a randomized comparison against an independent host reference, and the schema text as the source of truth for docs/ContribOperators.md (I compared the generated MoEGroupRouter section with bert_defs.cc; it matches).

Blocking (inline)

  1. moe_group_router_impl.cu:157 — int64_t grid size → MSVC C4244 / C2220 on every Windows CUDA job (example).
  2. linear_attention_gates.cc:300,302 — int64_t index into an InlinedVector → -Werror,-Wshorten-64-to-32 on wasm_Debug, wasm_Release and wasm_Release_static_library (example).

In the #34003 Windows CUDA job (which contains this layer's code) the other new/changed CUDA translation units (moe_packed.cu, matmul_packed.cu, gather_packed.cu, fused_state_space_impl.cu) compiled without warnings, so these two lines look like the whole delta for those platforms.

Independent verification (stack tip 623a725f5c, which contains this layer; Linux, CUDA 13.0, sm_80;sm_90a, Release; A100-SXM4-80GB)

  • Build OK; the stack's 60 provider tests pass, including MoEGroupRouterTest (9), MoEGroupRouterProjectionShapeInferenceTest (2) and MoEGroupRouterProjectionTest (11: randomized reference, ties, non-finite inputs, chained-vs-integrated, runtime-geometry negatives); compute-sanitizer synccheck, racecheck and initcheck are clean on them.
  • The CPU compact path runs in the same tests and also passed in the Windows CPU debug job of #34003 (onnxruntime_provider_test passed there; that job's only failure is onnxruntime_shared_lib_cpuinfo_dlopen_test, which this stack does not touch).

Non-blocking

  • Test gap for the compact-path guards — inline on CompactOutputsMustBePaired.
  • Public API surface: with compact outputs feeding MoEPacked inputs 5/6 (the "Graph wiring" in the description), MoEPacked's integrated sigmoid router (routing_function, router_scale, inputs 7–9, added in #33963) is a second public form of the same computation. See my inline comment on #33963; worth deciding before either ships.
  • Nit: the CPU compact path allocates two InlinedVectors of num_experts elements per row inside the parallel-for (heap allocations once num_experts exceeds the inline capacity); per-batch scratch hoisted out of the row body would avoid them. Low priority for a reference path.

@rui-ren
Rui Ren (rui-ren) force-pushed the rui-ren/bolt-standalone-router-on-33969-20261108 branch from 328a764 to e741e79 Compare November 10, 2026 02:46
@rui-ren
Rui Ren (rui-ren) force-pushed the rui-ren/bolt-standalone-router-on-33969-20261108 branch 2 times, most recently from 1e5355f to 80def95 Compare November 10, 2026 04:26
@tianleiwu
Tianlei Wu (tianleiwu) enabled stacked auto-merge (squash) November 12, 2026 05:36
stacked auto-merge was automatically disabled November 12, 2026 07:24

Auto-merge was disabled for another pull request in the stack

@tianleiwu
Tianlei Wu (tianleiwu) enabled stacked auto-merge (squash) November 12, 2026 07:25
stacked auto-merge was automatically disabled November 12, 2026 09:19

Auto-merge was disabled for another pull request in the stack

Rui Ren (rui-ren) and others added 13 commits November 12, 2026 15:59
Move Bolt sigmoid projection and route selection into a shared CUDA implementation with an independent MoERouterPacked operator. Preserve integrated graph compatibility, preselected routing semantics and packed expert arithmetic while making routing independently testable and maintainable.

Add FP16/BF16 routing tests and scoped schema/kernel documentation. Qualify the complete source-built runtime against preserved logits/state, route and complete same-mode generation controls; retain the existing ordinary-versus-k7 limitation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c8741c5a-3e9e-4860-b846-7d6fb0025040
Signed-off-by: rui-ren <ruiren1225@gmail.com>
Make MoERouterPacked schema documentation reproducible, document epsilon and nonfinite selection, infer both route output shapes, and validate every known input geometry before dimension access. Split CUDA host diagnostics with observed shapes and values without changing routing arithmetic.

Add CPU-only shape resolution coverage, distinct randomized FP16/BF16 routing references, same-lane ties, nonfinite activations, runtime geometry failures, and standalone-router-to-MoEPacked graph equivalence against integrated sigmoid routing and a nonuniform host reference. Verified bounded host/schema/test compilation, CPU/no-exception test compilation, targeted C++ lint, and exact schema/doc text rendering; runtime overlay validation remains coordinated separately.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f4d0e1a3-a389-4cc8-9c85-0fd0e3ffce5b
Signed-off-by: rui-ren <ruiren1225@gmail.com>
The executed 512-expert, 32-route fixtures could exhaust their bounded redraws while seeking a 1e-4 gap across every selected rank in three rows. Admit random reference data at the requested 1e-5 separation instead; indices remain exact and mixture-weight comparison tolerances are unchanged.

Fresh ABI-matched owned-head overlay on H100 GPU4: all 13 MoERouterPacked shape/router tests pass, including the standalone-router-to-MoEPacked graph comparison against integrated sigmoid routing. No production arithmetic changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f4d0e1a3-a389-4cc8-9c85-0fd0e3ffce5b
Signed-off-by: rui-ren <ruiren1225@gmail.com>
Replace the proposed MoERouterPacked operator with optional ordinary dense
projection and paired INT32 expert IDs / FP32 routing weights on the existing
CPU/CUDA MoEGroupRouter. Preserve its legacy grouped dense-output behavior.

Share the original projected-sigmoid arithmetic with integrated MoEPacked:
selection-only correction bias, deterministic ties, unbiased selected-rank
normalization and post-normalization scaling. This avoids changing effective
routing weights through a separate projection or a log/exp round trip.

Keep router weights unquantized and leave expert packing, expert arithmetic,
the MoEPacked schema and GenAI source unchanged. Add focused CPU/CUDA compact
routing tests and update the generated schema and kernel documentation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c8741c5a-3e9e-4860-b846-7d6fb0025040
Signed-off-by: rui-ren <ruiren1225@gmail.com>
Share observed-value projection validation between CPU and CUDA, including rank-one correction bias, without changing legacy grouped routing. Adapt the upstream negative-runtime tests to the optional projection interface and its INT_MAX row limit, and preserve the updated shape-inference diagnostics. The source-built runtime passes 40 provider/schema cases, six native GenAI cases, and the audited seven-GPU router comparison.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c8741c5a-3e9e-4860-b846-7d6fb0025040
Signed-off-by: rui-ren <ruiren1225@gmail.com>
Move the shared projected-sigmoid routing backend from cuda/bert to cuda/moe and update both MoEPacked and the existing MoEGroupRouter wrapper. Keep public operator contracts, routing arithmetic and kernel bodies unchanged.

Exclude the contrib wrapper from contrib-disabled builds so the BERT attention infrastructure does not retain an orphan reference to the moved backend. Validate all three affected translation units and production source selection for normal, contrib-disabled and minimal CUDA configurations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f4d0e1a3-a389-4cc8-9c85-0fd0e3ffce5b
Signed-off-by: rui-ren <ruiren1225@gmail.com>
Make bounded compact-route vector indices explicit size_t values for 32-bit WebAssembly builds. Explicitly convert the CUDA sigmoid-logit grid size to its unsigned launch dimension type for MSVC warning-as-error builds. Preserve routing arithmetic and keep the existing CI warning policy enabled.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c8741c5a-3e9e-4860-b846-7d6fb0025040
Signed-off-by: rui-ren <ruiren1225@gmail.com>
Replace the removed integrated-router comparison with direct checks of MoEGroupRouter expert IDs, FP32 mixture coefficients and chained MoEPacked output against the independent host reference. Preserve FP16/BF16 coverage and existing tolerances.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c8741c5a-3e9e-4860-b846-7d6fb0025040
Signed-off-by: rui-ren <ruiren1225@gmail.com>
Explicitly register the chained graph outputs so router IDs and FP32 coefficients remain fetchable even though MoEPacked consumes them. Preserve the independent host-reference assertions and tolerances.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c8741c5a-3e9e-4860-b846-7d6fb0025040
Signed-off-by: rui-ren <ruiren1225@gmail.com>
Address unresolved review feedback on #33994. Preserve the current router API separation and all upstream stack changes. Validated together in the native stack test matrix.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: rui-ren <ruiren1225@gmail.com>
(cherry picked from commit e51d8669a9bf5b207f42419f57de9feda3ef3ca8)
Signed-off-by: rui-ren <ruiren1225@gmail.com>
Add paired full-expert selection_scores and router_weights outputs while preserving existing legacy and compact modes. Keep bias in selection only and leave top-k, normalization and scaling to the expert consumer.

Reuse the existing FP32 projection/sigmoid arithmetic on CPU and CUDA. Cover full output shapes, all three dtypes, zero-row and exceptional values, and incompatible mode requests. Focused source-bound native tests passed on CPU and H100 CUDA; this is not full-model qualification.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: rui-ren <ruiren1225@gmail.com>
Connect unbiased full mixing values and biased selection scores directly to native MoEPacked, normalize inside the consumer, and apply scaling outside it. Preserve the previously qualified FP16/BF16 CUDA chain regression and its unchanged numerical gates. Synchronize on the consumer API without changing native expert weights or stack order.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: rui-ren <ruiren1225@gmail.com>
Keep the legacy dense output and expose full FP32 selection scores and unbiased mixing values at outputs 1 and 2. Remove compact expert indices/weights, router_scale, and their unused CPU/CUDA implementation and registration constraints; top-k, normalization, and model scaling belong to the consumer graph.

Migrate projection, shape, and chained MoEPacked regressions and regenerate the scoped schema/kernel documentation. Fresh native CPU/CUDA qualification passes 26 focused checks with zero skips using retained ORT support libraries; full-source CI is not claimed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: rui-ren <ruiren1225@gmail.com>
@tianleiwu
Tianlei Wu (tianleiwu) enabled stacked auto-merge (squash) November 12, 2026 21:14
@tianleiwu
Tianlei Wu (tianleiwu) merged commit cedae42 into main Nov 12, 2026
129 of 234 checks passed
@tianleiwu
Tianlei Wu (tianleiwu) deleted the rui-ren/bolt-standalone-router-on-33969-20261108 branch November 12, 2026 21:34
Tianlei Wu (tianleiwu) pushed a commit that referenced this pull request Nov 12, 2026
## Description

Optimizes the existing CUDA MatMulPacked and IQ2_XXS MoEPacked paths
without changing
operator schemas, packed-weight layouts, or exported graphs. NVFP4 uses
vectorized
group decoding, paired BF16 operands, and half-chunk staging for
eligible large-N
Hopper projections. Q8 uses aligned packed-record windows with
stride/alignment
fallbacks; dense IQ2 reconstructs complete BF16 operands using the
original K partitions.

IQ2 experts use exact magnitude-codebook reconstruction and
launch-selected aligned
FC1 activation loads. FP32 scale reconstruction, sign-before-BF16
rounding, FC1/FC2
warp partitions, ReLU-square boundaries, and final reduction order are
preserved.
The shared LoadPacked8 fallback from the standalone-router extraction is
reused.

**Dependency:** #33994 in
[native stack
#33967](https://github.com/microsoft/onnxruntime/stack/33967).
Mamba and standalone/integrated routing are unchanged. No
requantization, GenAI
inference change, graph conversion, or acceptance-threshold adjustment.

## Summary of Changes

### Packed Projection and Expert Kernels

| File | Change |
|------|--------|
| `onnxruntime/contrib_ops/cuda/quantization/gguf_quant_cuda.cuh` | Add
vectorized NVFP4/Q8 loads and dense IQ2 BF16 operand reconstruction. |
| `onnxruntime/contrib_ops/cuda/quantization/matmul_packed.cu` | Select
eligible optimized paths while retaining architecture/alignment
fallbacks. |
| `onnxruntime/contrib_ops/cuda/moe/moe_packed_iq2.cuh` | Add IQ2 expert
codebook/operand helpers with exact FP32 scale reconstruction. |
| `onnxruntime/contrib_ops/cuda/moe/moe_packed.cu` | Use the expert
helpers and aligned FC1 activation-load specialization. |

### Regression Tests

| File | Change |
|------|--------|
| `onnxruntime/test/contrib_ops/matmul_packed_precision_test.cc` | Cover
production projection widths, NVFP4 operand extremes, Q8 record
windows/stride fallback, and IQ2 complete operands. |
| `onnxruntime/test/contrib_ops/moe_packed_routing_test.cc` | Add
production-width and IQ2 codebook/scale reconstruction cases. |
|
`onnxruntime/test/contrib_ops/cuda_kernels/matmul_packed_kernel_test.cc`
| Pin the compiled TC contiguous-128-K reduction for small/staged NVFP4
paths. |
| `onnxruntime/test/python/transformers/test_gguf_packed_ops.py` |
Exercise default-rounded byte-offset IOBinding fallbacks without a model
precision attribute. |

## Testing

**Session-policy compatibility update:** head
`6294c1fd47b493fc5dbbbed6cfad3cc406ca476e`, rebased onto
the default-rounded MatMulPacked contract from #33962. The removed node
attribute is no
longer emitted by test model factories or assigned through internal
launch parameters.
Default numerical references round weights for both activation dtypes
and every dispatch.

**Validation at optimized stack tip
`a3f2076b65e0d1a5c7e9b82165ffab014e233876`:** 15 native CUDA + 15
compute75-only PTX projection tests, 5 Python format/policy/alignment
tests, and 1 actual
internal CUDA contiguous-128-K cancellation test; zero failures/skips.
CLANGFORMAT,
Ruff/format and whitespace checks pass.

These are focused ABI-matched overlays with fresh changed objects, **not
a clean full-source
build, full CI, performance remeasurement, or new full-model
qualification**. The previous
broader review qualification and historical performance results are
preserved below.

<details>
<summary>Historical measurements and qualification evidence (not
current-head acceptance)</summary>

### Earlier review qualification (historical)

**Review-fix snapshot:** `74847ad6021d5b5431fa5984efb7fa95f6a310cd`.

Added offset-buffer IOBinding fallbacks (NVFP4/Q8 and IQ2 ReLU-square
MoE), nonuniform single-product and bitwise 8-vs-9-row MoE oracles,
all-256-position IQ2 one-hot coverage, NVFP4 high-nibble coverage and an
actual internal contiguous-128-K cancellation regression. Removed
duplicate IQ2 table/decoder logic and dead branches; lowered the
operand-extremes fixture gate to SM80. Seven wrong-mapping mutations
produce nonzero output differences in the new oracle.

**Owning-layer validation:** 20 C++ + 2 Python IOBinding + 1 actual
internal CUDA cancellation test; zero failures/skips.

**Integrated tip regression:** 51 C++ provider/schema tests, 5 actual
internal CUDA tests and 2 Python IOBinding tests passed, zero
failures/skips. All owning-layer provider cases are retained. The final
overlay recompiles the changed CUDA/host/schema/test sources over
ABI-matched preserved ORT support; **not a clean full-source build,
full-CI approval, independent HF parity or new end-to-end
qualification**. Targeted configured clang-format/Ruff and whitespace
checks passed.

These previously reported results are retained for provenance. They have
not been rerun on the rebased head above; earlier CI/build status and
benchmark results do not establish current-head CI, accuracy, or merge
readiness.

Original comparison pins: parent #33994 at
`a8ff5642f5c85519561964928006413a4fde7859`; candidate
`1b5063c4af651e12bf955bc978c9312e2734a9f9`.

**This is the actual stack-tip comparison**, not the earlier
private-branch
versus #33940 comparison. That distinction matters: the remote stack tip
did
not yet contain the optimized native kernels.

| Input tokens | Stack ordinary tok/s | Candidate ordinary tok/s | Stack
k=7 tok/s | Candidate k=7 tok/s |
|---|---:|---:|---:|---:|
| 178-254 | 54.36 | **92.42** | 223.84 | **355.42** |
| 427-932 | 54.20 | **92.08** | 185.24 | **293.62** |
| 1028-1663 | 54.25 | **92.04** | 201.48 | **318.91** |

Approximately **70% ordinary** and **58-59% k=7** improvement in this
controlled
comparison. This does not claim that all remaining latency is resolved.
The separate #33940 equivalent-package result of approximately 109
ordinary /
370 k=7 tok/s on the longest bin is **not** a measurement of this
candidate;
transferring that remaining gain is still outstanding.

Protocol: original frozen 30 real prompts, ten per bin, unchanged
warmups and
per-prompt mode order, natural EOS/512-new-token cap, two reversed-order
passes,
same physical H100 per baseline/candidate shard. Eight logical shards
ran in
waves over GPUs 1,3,4,5,6,7. All admitted runs passed the foreign-client
and
resource guards. No profiler ran in the timing window; clocks were not
locked.
Rates pool decoded tokens over elapsed decode time, excluding the first
token,
not arithmetic means of per-request TPS.

## Correctness and build validation

- Exact same native model package, packed bytes and GenAI libraries in
both arms.
Graph hashes match the preserved source-value audit; full package-file
hashes
  were recorded again. No exported checkpoint/package was modified.
- **22 native CUDA regressions passed, zero skips**, covering
projections,
complete operand rounding/cancellation, IQ2 production widths/codebook
scales,
routing and the standalone router. Changed C++ files passed CLANGFORMAT;
  git whitespace checks passed.
- **1,782 complete live tensor/state hashes per arm**, bitwise equal and
finite
in ordinary and k=7 modes, also equal to the preserved quantized
control.
- Independent full LCB145 ordinary/k=7 probes passed all **512 generated
tokens**
  and complete counters.
- The accepted timing run passed **240 complete measured generation
sequences**
against frozen ordinary-control tokens. Within-mode complete speculative
  counter dictionaries matched between arms and repeats.
- Isolated incremental rebuild on the archived clean #33994 build; every
affected compilation unit/header dependent was rebuilt and the
provider/test
binary relinked with the production flags. Untouched objects were
reused:
  **this is not a new clean full-source build**.
- CUDA 12.8.93, driver 580.159.04, H100 80GB. Common corrected GenAI
source:
  `c0fd01914265d5157d6da1376c38b4df521a76c5`

([microsoft/onnxruntime-genai#2916](microsoft/onnxruntime-genai#2916)).
Both arms use that same source; its correctness fix is not credited with
the
  kernel speedup.

Accepted statistics SHA256:
`0b9b7e2385b2dd9d7e5f7d459c65ef74338b5f707d1536454e7e27fb9a407c0f`.

</details>

## Checklist

- [x] Review feedback addressed with focused regressions
- [x] Documentation and supported contracts updated
- [x] Native stack order and immediate-parent dependencies preserved
- [ ] Clean full-source/full-CI qualification (not claimed by focused
overlays)


### Python IQ2 alignment regression correction

Commit `f6e5af95c1` migrates
`test_moe_packed_relu_iq2_aligned_input_fallback` from the removed
seven-input compact-routing interface to six-input full-score routing:
`[X, R, G, "", D, W]`, with FP32 selection scores and mixing values.
Explicit `normalize_routing_weights=0`, buffer offsets and the exact
bitwise oracle remain unchanged. No production code changes.

The original test was reproduced failing graph resolution (7 inputs;
schema maximum 6). The corrected actual Python unittest passed on H100
with zero skips, including all four combinations of rows 8/9 and
activation offsets 0/2. Profiles confirm four
`CUDAExecutionProvider/MoEPacked` executions. Ruff lint/format and
whitespace checks passed.

This run used the retained six-input full-score ORT 1.32.0 runtime built
from `3bf5237cd65131701f2fb05435774672afaf1f96`; it is not a fresh
runtime build of this PR, a full Python suite, or full CI approval. The
corrected test file is byte-identical in the synchronized #34003 head.

---------

Signed-off-by: rui-ren <ruiren1225@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f4d0e1a3-a389-4cc8-9c85-0fd0e3ffce5b
Tianlei Wu (tianleiwu) added a commit that referenced this pull request Nov 13, 2026
This cherry-picks the following commits for the release:

| Commit ID | PR Number | Commit Title |
|-----------|-----------|-------------|
| 85dcb54 | #32475 | Update Eigen to 5.0.1 + SSE2 fix (broken Clip &
Sign) |
| 1ea552d | #33976 | [CUDA/CPU] Add hybrid GPU/CPU expert offload for
MoEPacked block-packed weights |
| 3a8b8f2 | #34066 | [CUDA] Optimize multi-token MatMulPacked GGUF
GEMV (M=2..8) and eliminate ReadU32Dev warp divergence |
| 64506ea | #34098 | [CUDA] Guard tests requiring SM80 on older GPUs
|
| 74f861c | #34067 | [MoE] Optimize multi-token (M=4, 8) MoEPacked
CPU hybrid cold routes and GPU FC2 decode |
| 6aa9b27 | #33963 | [CUDA] Extend MoEPacked for top-k, dispatch and
fused MoE calculation |
| 8fb1b27 | #33969 | [CUDA] Add Mamba2Verify CUDA Kernel |
| cedae42 | #33994 | [CUDA] Update `MoEGroupRouter` for routing to
`MoEPacked` |
| 158d0c0 | #34002 | [CUDA] Speed up native Bolt packed projections
and IQ2 experts |
| 38c6dce | #34003 | [CUDA] Reduce native packed decode tile and FC2
loader overhead |
| d5704db | #34147 | [CUDA] Optimize MoEPacked, MoEGroupRouter, and
MatMulPacked for Nemotron Bolt |
| 7cca0e5 | #34126 | Fix Windows junction detection in model_package
for non-MSVC standard libraries |
| 2bf400a | #34099 | Fix external data validation for Hugging Face
Hub shared blob store |
| d2f77cd | #34164 | [CUDA] Accelerate Nemotron Bolt large-chunk
prefill across contrib ops |
| ca7ea48 | #28457 | Add set_default_logger_callback Python API for
custom ORT logging |
| fca9447 | #34117 | [CUDA] Optimize CUDA prefill and quantized paged
attention |
| 1804c6f | #34114| [CUDA] Optimize
MoEPacked GGUF offload 3-stage prefill pipeline and F16C/Batch4/40-core
cold decode |

---------

Signed-off-by: Christian Bourjau <christian.bourjau@quantco.com>
Signed-off-by: rui-ren <ruiren1225@gmail.com>
Co-authored-by: Christian Bourjau <cbourjau@users.noreply.github.com>
Co-authored-by: BBaditi <bbaditi@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Rui Ren <ruiren1225@gmail.com>
Co-authored-by: Mustapha Jaber <mustjab@users.noreply.github.com>
Co-authored-by: Mustapha Jaber <mustjab+microsoft@microsoft.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
Copilot-Session: f4d0e1a3-a389-4cc8-9c85-0fd0e3ffce5b
Copilot-Session: c8741c5a-3e9e-4860-b846-7d6fb0025040
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.

3 participants