Repository navigation
[CUDA] Add Mamba2Verify CUDA Kernel - #33969
Tianlei Wu (tianleiwu) merged 7 commits into
Conversation
a114167 to
970a1a9
Compare
e098716 to
374c7d5
Compare
Source-pinned H100 kernel evidence - 2026-11-07BF16 projection/convolution, FP32 SSM state; 128 heads, eight groups, head dimension 64, state size 128, channels 10240, projection stride 18560, four-tap convolution. One fused R-row production launch is compared with R serial single-row production calls with exact state handoff; every timed invocation starts from the same immutable initial state. This compares three fused kernels with 3*R serial kernels. Frozen Bolt precision contract: FP32 gate/normalization/gamma followed by BF16 output; this is not an acceptance test for the earlier Lightning cast-before-gamma contract. Conv snapshots, SSM snapshots and xBC are bitwise equal for all three cases in both runs. Y/readout pass normalized RMSE <=0.03 and cosine >=0.999; exact raw metrics are below. The one-row control is approximately unchanged; eight/sixteen-row fusion reduces latency.
H100 80GB HBM3, CUDA 12.8.93, driver 580.159.04, GCC 11.4.0. CUDA-event median per dispatch; 64 dispatches per captured CUDA graph, 50 warmups, three graph warmups, and 15 paired timed batches alternating AB/BA. Four rotating allocation banks contain deterministic synthetic weights (seed 617); this is not a cold-cache guarantee or a checkpoint-weight benchmark. Raw p95 values describe batch-average latency, not individual-invocation tails. No profiler runs in the timing window. The assigned GPU had empty admission, one stable compute client during execution, and clean release afterward; clocks were not locked. Two independent 39-case runs passed, including the published replay runner. Scope: same-build production CUDA dispatch alternatives, not historical parent-commit binaries. The measured runtime is an isolated CUDA provider relink with preserved core/support, not a clean full-source ORT build or end-to-end model qualification. Each measured operator's CUDA source hash matches its owning PR head. A clean source build is a separate replication variant and must be measured again. Kernel-only timings do not establish model TTFT/tok/s, MMLU/LCB, speculative integration, or full-model readiness. Source/runtime hashes and supervision receipts{
"operator_sources": {
"projection": {
"head": "ca5bf6a4c1308b4374238b37884d07edf4c3bae5",
"cuda_sha256": "9df42138bbe8cbd40114307053398db59f64a5ab25908361a8a655230ce90e71"
},
"moe": {
"head": "a9bdbce374a3b2757e1fd11ef83ce6f83502b0d9",
"cuda_sha256": "7d9a1454e416753b61342cd78c3ba11f90308320d58f96cc5361c6bfa6ffa486"
},
"mamba": {
"head": "374c7d51d93bfdd29cb0f2efbc76b88e1e812aa7",
"cuda_sha256": "5e2568fe8aa5794456bf84f122b2e50020f050572043d578fb736ea03796923a"
}
},
"loaded_library_sha256": {
"libonnxruntime.so.1.32.0": "8e08a5f9b0ae8e67f31bbeaea1942a14f97d2a568d62f1e6b13ad72fcc187d4c",
"libonnxruntime_providers_cuda.so": "c1b303583039d412416a5aabc04c1748a2d5433ce691c4aa10b9d58ab3d76e0a",
"libonnxruntime_providers_shared.so": "98cc35d20a8701b425d3b51ebbbd9186744c9abcec5d2270879f6c165a735228"
},
"cuda": "12.8.93",
"driver": "580.159.04",
"host_compiler": "GCC 11.4.0",
"device": "NVIDIA H100 80GB HBM3",
"seed": 617,
"allocation_banks": 4,
"primary_supervisor": {
"status": "PASS",
"worker_exit": 0,
"peak_process_bytes": 3147825152
},
"repeat_supervisor": {
"status": "PASS",
"worker_exit": 0,
"peak_process_bytes": 3147825152
},
"scope": "Isolated production CUDA dispatch microbenchmark; recorded production objects/flags linked with preserved ORT support, NOT a clean full runtime or end-to-end model benchmark.",
"cuda_and_host_dependency_sha256": {
"libcudnn_graph.so.9": "2e8a0e4e66c0c8f9dc273c486698614c0561832626fadf76a8a37b94d0e2f895",
"libcudnn.so.9": "0f43113ec6b171f93236560541f3b95104fed2516b19000a0e7047a5cc12f8ee",
"libcuda.so.580.159.04": "821992937649fe6b01b0633fa4f47665ff5c02f273ea4696763ad19154cb7c55",
"libcudart.so.12.8.90": "c3a75b33af334a3486d197dbd1584a2985183ba4688d237a2be5f2f679329920",
"libcublas.so.12.8.4.1": "031ce6c2cbfbb9468f040527cab5c599069ce5609e73e28f87503881063eac21",
"libcublasLt.so.12.8.4.1": "10b5e6631cf8115c661eb895ed1533826308b58f7956466f53d236a40c9b622c",
"libstdc++.so.6": "1fd75fe70354a416d75aef22bcae68c47bd25d20e2d0568c30b1a9838cf62f11",
"libc.so.6": "3a15d66867d83762c7f2f1e37359cb8f6c5743edb369c65285cb0b1c4f7498bf"
},
"production_cuda_codegen_options": [
"-O3",
"-std=c++20",
"--generate-code=arch=compute_90a,code=[sm_90a]"
]
}Primary run: all cases, numerical metrics and all paired latency samples{"pr":33969,"op":"Mamba2Verify","rows":1,"heads":128,"groups":8,"head_dim":64,"state_size":128,"correctness":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"conv_state":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"ssm_state":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"xbc":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"readout":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"baseline":{"median_us":8.909000084,"batch_p95_us":8.926300146,"trials_us":[8.948000148,8.917000145,8.917000145,8.903999813,8.906000294,8.905000053,8.912499994,8.901000023,8.905500174,8.909500204,8.910000324,8.909000084,8.910999633,8.906999603,8.907499723]},"current":{"median_us":8.910999633,"batch_p95_us":8.914550208,"trials_us":[8.910000324,8.910999633,8.902999572,8.911499754,8.906500414,8.917000145,8.913500234,8.906999603,8.910999633,8.913500234,8.909500204,8.912499994,8.907999843,8.908499964,8.913500234]}}
{"pr":33969,"op":"Mamba2Verify","rows":8,"heads":128,"groups":8,"head_dim":64,"state_size":128,"correctness":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"conv_state":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"ssm_state":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"xbc":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"readout":{"nrmse":6.08055523951e-08,"cosine":1,"max_abs":7.45058059692e-09,"bitwise":false},"baseline":{"median_us":82.982502878,"batch_p95_us":83.074299246,"trials_us":[83.089001477,82.929499447,82.973003387,82.982502878,83.06799829,82.997001708,83.065502346,82.953996956,82.974500954,82.959502935,83.065502346,82.901999354,83.008997142,82.908503711,82.9859972]},"current":{"median_us":22.168500349,"batch_p95_us":22.269850411,"trials_us":[22.153500468,22.141499445,22.220000625,22.210000083,22.216500714,22.208500654,22.168500349,22.215500474,22.286999971,22.140000015,22.262500599,22.110000253,22.151000798,22.144500166,22.139500827]}}
{"pr":33969,"op":"Mamba2Verify","rows":16,"heads":128,"groups":8,"head_dim":64,"state_size":128,"correctness":{"nrmse":4.23097936912e-09,"cosine":1,"max_abs":2.38418579102e-07,"bitwise":false},"conv_state":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"ssm_state":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"xbc":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"readout":{"nrmse":6.15534900543e-08,"cosine":1,"max_abs":1.49011611938e-08,"bitwise":false},"baseline":{"median_us":167.011499405,"batch_p95_us":167.137302458,"trials_us":[167.110994458,167.027503252,167.034998536,167.187005281,167.011499405,166.930004954,166.954502463,166.852995753,166.971504688,166.990503669,167.058005929,167.006492615,167.054504156,166.977003217,167.116001248]},"current":{"median_us":41.409499943,"batch_p95_us":41.497398913,"trials_us":[41.386000812,41.437998414,41.49049893,41.478998959,41.390001774,41.390001774,41.429001838,41.513498873,41.450001299,41.409499943,41.407998651,41.381001472,41.288498789,41.375499219,41.450999677]}}Independent replay: all cases, numerical metrics and all paired latency samples{"pr":33969,"op":"Mamba2Verify","rows":1,"heads":128,"groups":8,"head_dim":64,"state_size":128,"correctness":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"conv_state":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"ssm_state":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"xbc":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"readout":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"baseline":{"median_us":8.898000233,"batch_p95_us":8.945599757,"trials_us":[8.988999762,8.895000443,8.899499662,8.926999755,8.898000233,8.897500113,8.901500143,8.902500384,8.890500292,8.895499632,8.893500082,8.906999603,8.895999752,8.892999962,8.918999694]},"current":{"median_us":8.907999843,"batch_p95_us":8.976550307,"trials_us":[8.985999972,8.911999874,8.898000233,8.905500174,8.907999843,8.911499754,8.899499662,8.937000297,8.906000294,8.910500444,8.972500451,8.904499933,8.897500113,8.911999874,8.902999572]}}
{"pr":33969,"op":"Mamba2Verify","rows":8,"heads":128,"groups":8,"head_dim":64,"state_size":128,"correctness":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"conv_state":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"ssm_state":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"xbc":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"readout":{"nrmse":6.08055523951e-08,"cosine":1,"max_abs":7.45058059692e-09,"bitwise":false},"baseline":{"median_us":82.964003086,"batch_p95_us":83.073948324,"trials_us":[83.073496819,82.887999713,82.932502031,82.936502993,82.95699954,82.964003086,83.075001836,83.007998765,82.948498428,83.010002971,83.008997142,82.958996296,83.030998707,82.956500351,82.99549669]},"current":{"median_us":22.196000442,"batch_p95_us":22.263199277,"trials_us":[22.210000083,22.120000795,22.248499095,22.200999781,22.162999958,22.126499563,22.297499701,22.200999781,22.19549939,22.138999775,22.17900008,22.206500173,22.196000442,22.193999961,22.231999785]}}
{"pr":33969,"op":"Mamba2Verify","rows":16,"heads":128,"groups":8,"head_dim":64,"state_size":128,"correctness":{"nrmse":4.23097936912e-09,"cosine":1,"max_abs":2.38418579102e-07,"bitwise":false},"conv_state":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"ssm_state":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"xbc":{"nrmse":0,"cosine":1,"max_abs":0,"bitwise":true},"readout":{"nrmse":6.15534900543e-08,"cosine":1,"max_abs":1.49011611938e-08,"bitwise":false},"baseline":{"median_us":166.695997119,"batch_p95_us":166.899549961,"trials_us":[166.887998581,166.677996516,166.770502925,166.672497988,166.695997119,166.72000289,166.675001383,166.553497314,166.81599617,166.595995426,166.926503181,166.62299633,166.721999645,166.650503874,166.757002473]},"current":{"median_us":41.581001133,"batch_p95_us":41.67464897,"trials_us":[41.581001133,41.566498578,41.480001062,41.623000056,41.576001793,41.713498533,41.613999754,41.55600071,41.521999985,41.609998792,41.657999158,41.465498507,41.444499046,41.634000838,41.632000357]}}Benchmark source, synthetic setup graph and validated replay runner: #33962 (comment) |
There was a problem hiding this comment.
🟡 Changes recommended
Shape inference incorrectly accepts rank-1 convolution weights that runtime execution rejects; input 3 needs explicit rank-2-or-3 validation and a rank-1 regression test.
1 open issue
What changed in this PR
Adds com.microsoft::Mamba2Verify as a built-in CUDA contrib operator above the packed-operator stack. It fuses causal convolution, selective recurrence and gated grouped RMS normalization with caller-selected state snapshots.
Changes:
- Adds the operator schema, CUDA registration and implementation for 1–16 token rows.
- Supports post-token snapshots, state-buffer aliasing, trailing-slot preservation and invalid-selector handling.
- Adds provider/internal regression tests and operator documentation; full-model qualification remains separate.
| File | Description |
|---|---|
onnxruntime/test/contrib_ops/fused_state_space_op_test.cc |
Tests outputs, snapshots, aliasing and registration. |
onnxruntime/test/contrib_ops/cuda_kernels/fused_state_space_test.cc |
Tests large normalization grids and offset weights. |
onnxruntime/core/graph/contrib_ops/fused_state_space_defs.h |
Defines the schema and shape inference. |
onnxruntime/core/graph/contrib_ops/contrib_defs.cc |
Registers the contrib schema. |
onnxruntime/contrib_ops/cuda/sequence/FusedVerification.md |
Documents contracts, precision and validation scope. |
onnxruntime/contrib_ops/cuda/sequence/fused_state_space.cc |
Validates inputs and manages snapshot outputs. |
onnxruntime/contrib_ops/cuda/sequence/fused_state_space_impl.h |
Declares CUDA launch interfaces. |
onnxruntime/contrib_ops/cuda/sequence/fused_state_space_impl.cu |
Implements convolution, recurrence and normalization kernels. |
onnxruntime/contrib_ops/cuda/cuda_contrib_kernels.cc |
Registers the CUDA kernel. |
docs/OperatorKernels.md |
Lists CUDA kernel support and types. |
docs/ContribOperators.md |
Adds the generated operator reference. |
Review effort: Balanced
374c7d5 to
3ec958c
Compare
3ec958c to
5809f25
Compare
Rui Ren (rui-ren)
left a comment
There was a problem hiding this comment.
Stack #33967 review — parent e50e34972b24 -> head 5809f2531dcb.
Reviewed snapshot layouts and selectors, output initialization/preservation, corresponding state-buffer aliasing, BF16/FP32 boundaries, schema/registration, and stream ordering.
Confirmed the existing load-time validation gap in the conv_weight rank thread: input 3 currently accepts ranks {1,2,3}, because rank 1 falls through to the generic rank-one rule. For heads=4/groups=2, an otherwise-valid model with conv_weight[3072] passes that rank predicate but ComputeInternal rejects it as "Invalid convolution parameters". Handle input 3 separately and reject known ranks other than 2/3; add a Graph::Resolve rank-one regression. This is delayed validation, not a demonstrated unsafe CUDA access.
No additional high-confidence correctness finding. The single-row/multi-row readout-order distinction is addressed by #34003's multi-slot replay change. Validation here was source/control-flow review plus a host reproduction of the rank predicates, not an actual Graph::Resolve run or new CUDA/capture test.
Tianlei Wu (tianleiwu)
left a comment
There was a problem hiding this comment.
Reviewed this layer (stack #33967, layer 3) at 5809f2531d.
Kernel and host review. I compiled the PR's .cu standalone (CUDA 13.3, H200) and compared it with an independent FP32/BF16 reference over several hundred geometry/row/slot/selector combinations, including the production 128-head / 8-group / 1024-wide-group shape. Aliased and non-aliased runs were bitwise identical, trailing slots were preserved, out-of-range selectors produced NaN rows, compute-sanitizer (memcheck, racecheck, initcheck, synccheck) was clean, and CUDA-graph replay with a device-updated selector worked. I found no correctness defect in the kernels or the host code. (Not run: an ORT build and the OpTester-based tests; only the CUDA translation unit was exercised.)
Open from the existing review. A rank-1 conv_weight still passes shape inference (thread on fused_state_space_defs.h; the checklist item in the PR description is unchecked). I added a concrete predicate and a GPU-independent regression suggestion on that thread. This should be fixed before merge.
Requests (inline, none blocking on its own)
- Test strength:
Y/xbcuse the default BF16 tolerance; thetime_step_minclamp and theraw > 20branch are never exercised; the production 1024-wide norm branch only sees uniform gate/gamma; andOnlyMambaRemainsAmongProvisionalOperatorsasserts the absence of names that do not exist in the tree. - Docs: the schema doc should state
slots >= Rand the NaN policy for an out-of-rangestate_row;FusedVerification.mdcarries provenance that cannot be verified after merge and sits outside thedocs/contrib_ops/cuda/convention.
Minor / design notes
- Validation messages ("Invalid head parameter", "Invalid convolution parameters", "Invalid norm weight or state_row") do not name the input or the expected/actual shapes. With ten inputs and a rigid derived geometry that makes exporter mistakes hard to diagnose.
xbcandreadoutare kernel-internal intermediates (the scratch buffers passed between the conv, SSM and norm kernels) but are required outputs of a stablecom.microsoftv1 op. Every call allocates and writes them (about 327 KB + 524 KB at R=16 for 128 heads / 8 groups), and any future fused implementation must still materialize them to honor the ABI. If they exist for qualification only, consider making them optional outputs; otherwise accept the ABI freeze consciously.- Cross-layer: at this head a single-row call runs
MambaSsmKernel<2>while multi-row calls runMambaSsmKernel<4>, so the readout reduction order differs between serial single-row replay and an R-row call (a few BF16Yelements can differ in a standalone comparison). #34003'srows > 1 || slots > 1dispatch addresses this for multi-slot caches, as the PR description acknowledges. Until then the test references here still encode the old partition (parts = rows == 1 ? 2 : 4) and only keep passing because of the tolerances. fused_state_space_impl.hL15 documents snapshots as[rows, heads, state_size, head_size], but the buffers are[slots, heads, d_state, head_dim]withslots >= rows; andMambaInvalidSelectorsProduceNaNWithoutStateReadscannot observe state reads (outputs are NaN either way), so its name over-claims.
4f2bd30 to
10c6969
Compare
Tianlei Wu (tianleiwu)
left a comment
There was a problem hiding this comment.
Re-review of 10c6969943.
Verdict: COMMENT — no blocking findings.
Earlier threads, re-checked on this head — all eight are fixed:
- explicit per-input rank predicate + known-dimension validation, with CPU-only schema regressions outside the CUDA guard;
time_step_minclamp /raw > 20coverage, and a NaN-propagating clamp (dt < tmin ? tmin : dt) withMambaTimeStepNaNPropagates;- ULP-aware
Y/xbccomparison instead of the default BF16 tolerance; - nonuniform coverage of the 1024-wide normalization branch;
- the "absent names" test removed;
slots >= Rand the invalid-selector NaN policy are in the public schema / op reference;- the contract moved to
docs/contrib_ops/cuda/mamba2_verify.md, with provenance removed from in-tree docs.
I also read the three kernels for hazards: aliasing is safe by construction (every thread reads its own conv-channel / SSM slice of the selected snapshot before writing any output row, and slices are disjoint across threads and blocks, so state_row < R with in-place state cannot race); the invalid-selector return precedes every __syncthreads() and is block-uniform; shuffles use full masks; 64-bit index math covers the snapshot offsets and heads <= INT_MAX / 1024 bounds the int channel/stride arithmetic.
Independent verification (stack tip 623a725f5c, which contains this layer; Linux, CUDA 13.0, sm_80;sm_90a, Release; A100-SXM4-80GB)
FusedStateSpaceSchemaTest(3),FusedStateSpaceTest(8) and the internalFusedStateSpaceKernelTest(4) pass; the full stack set (60 provider tests) also passes 3x in shuffled order.compute-sanitizersynccheck, racecheck and initcheck including all Mamba tests: no findings.- CI on this head has no failures so far.
Nits (non-blocking): the constructor ORT_ENFORCE has no message (inline). The op is Mamba2Verify, but the sources, schema header and test suites are named fused_state_space* / FusedStateSpace*, so grepping for the op name misses them; renaming to match (the docs page already does) would help future maintenance.
10c6969 to
5491448
Compare
Auto-merge was disabled for another pull request in the stack
0de24b7 to
8559c5a
Compare
Auto-merge was disabled for another pull request in the stack
Auto-merge was disabled for another pull request in the stack
Retain the source-exact causal convolution, selective recurrence and gated grouped normalization implementation from #33940 above the packed MoE layer. Preserve device-selected starting snapshots, post-token states, aliasing, trailing storage and invalid-selector behavior without adding routing or projection operators. Include native schema/kernel registration and focused provider/internal tests. Production host, CUDA, schema, registry and test compilation passed. Live CUDA execution is NOT_RUN because this session currently has no device access; retain the PR as draft pending full-source runtime qualification. Signed-off-by: rui-ren <ruiren1225@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: rui-ren <ruiren1225@gmail.com>
Refresh canonical operator documentation from the exact Mamba-layer CI artifact. Inherit the repaired projection and MoE CI dependencies and fixtures while leaving Mamba recurrence, normalization, cache handling and dispatch unchanged. The previous composite Windows CUDA job executed all seven Mamba provider tests and both internal Mamba tests successfully. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: rui-ren <ruiren1225@gmail.com>
The Mamba CI artifact was produced against its former intermediate base, whereas lower-layer doc artifacts were generated against newer main. Retain only the canonical Mamba2Verify additions and preserve all inherited GQA contracts and WebGPU type registrations, avoiding unrelated stale-document changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: rui-ren <ruiren1225@gmail.com>
Introduce the multi-slot single-row replay reduction correction with Mamba2Verify, together with its bitwise replay regression and a cancellation-sensitive single-slot regression. Keep both host references consistent with the cache-capacity-dependent partition count. Reject invalid known geometry during shape inference, including rank-one convolution weights, and exercise schema resolution without CUDA. Preserve NaN time steps through the clamp, cover lower clamping and large raw values, and enforce BF16 ULP plus mismatch-fraction checks with nonuniform 1024-wide normalization coverage. Remove the nonexistent-operator history test and publish durable Mamba documentation under docs/contrib_ops/cuda, with selector, snapshot and precision contracts reflected in the generated operator reference. 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>
Address unresolved review feedback on #33969. 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 63854bfbf6dfe93ee7abd1ef28b2bcf869a0168f) Signed-off-by: rui-ren <ruiren1225@gmail.com>
Use stream-aware internal workspace when xbc or readout is omitted, while preserving required state outputs, CUDA arithmetic and replay behavior. Cover all output combinations, state aliases, invalid selectors, trailing snapshots and CUDA graph capture/replay. Document the Bolt-specific single-sequence scope and retained SSM layout, and preserve the numerical contract separately from eight-row dispatch details. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: rui-ren <ruiren1225@gmail.com>
Use the CudaKernel GetComputeStream(context) helper for optional xbc and readout scratch allocations. The plugin OpKernelContext adapter does not expose GetComputeStream(), while the helper supports both CUDA build modes and registers the plugin framework stream for allocator lifetime tracking. Reproduced the previous plugin compile error; the fixed translation unit compiles in regular CUDA and plugin-adapter modes. All 15 Mamba schema and CUDA provider regressions pass without skips in an isolated runtime overlay. 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>
8559c5a to
715972d
Compare
## 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](https://github.com/microsoft/onnxruntime/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`. <details> <summary>Historical PR description and earlier-head evidence (not current-head acceptance)</summary> ### 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 #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. </details> --------- Signed-off-by: rui-ren <ruiren1225@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c8741c5a-3e9e-4860-b846-7d6fb0025040 Copilot-Session: f4d0e1a3-a389-4cc8-9c85-0fd0e3ffce5b
## Description Reduces CUDA packed decode tile/loader overhead above #34002. Narrows eligible eight-row IQ2 FC1 tiles, adds aligned record-window reconstruction for eligible IQ2 FC2 rows, and uses full-tile NVFP4 paths only when their shape/alignment guards hold. Unsupported geometries retain the existing fallback. **Dependency:** #34002 in [native stack #33967](https://github.com/microsoft/onnxruntime/stack/33967). No schema, packed layout, cache/mask precision workaround, or GenAI source change. The R8-prefill/R1-ordinary hybrid session/package work is in the companion microsoft/onnxruntime-genai#2916, **not implemented by this native-kernel PR**. ## Summary of Changes ### Packed Decode Specializations | File | Change | |------|--------| | `onnxruntime/contrib_ops/cuda/moe/moe_packed.cu` | Select narrower FC1 tiles and eligible aligned FC2 loader variants. | | `onnxruntime/contrib_ops/cuda/quantization/gguf_quant_cuda.cuh`, `onnxruntime/contrib_ops/cuda/moe/moe_packed_iq2.cuh` | Reuse the shared IQ2 decoder for aligned word windows, including two-byte-offset records. | | `onnxruntime/contrib_ops/cuda/quantization/matmul_packed.cu` | Specialize eligible full NVFP4 output tiles while preserving guarded fallbacks. | | `onnxruntime/test/contrib_ops/moe_packed_routing_test.cc` | Exercise eight-row width/routing boundaries and larger intermediate widths. | ## Testing **Review-fix snapshot:** `ed6e6e1991fd944f65f1d97472d3f29046d97361`. Bound aligned-window FC2 to four resident CTAs, kept the R8-specific narrow FC1 gate decode-only (`!use_prefill_tiles`), simplified the FC2 guard to its real row/base alignment invariant, and reused the lower shared decoder. Nonuniform regression protection is introduced in #33963/#34002. Mamba replay changes were moved into their owning PR #33969; this layer no longer changes Mamba numerics or tests. **Owning-layer validation:** Integrated stack regression run and exact-production-kernel H100 A/B below. **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. ### Review-requested kernel A/B (H100, CUDA 12.8.93) Exact production kernel/helper text from the integrated head; random nonuniform IQ2, 512 experts, 16 rotating route sets, R=8. All variant outputs are bit-identical across all route sets. CUDA-event median: 20 warmups, 9 alternating batches x32 launches; no full-model/cold-cache guarantee. `k=9` is decode, `k=17` is four-subtile prefill; the latter remains excluded from the narrow dispatch. | Hidden | Inter | k | FC1 wide→narrow μs | FC2 plain / window / hinted μs | |---:|---:|---:|---:|---:| | 1024 | 1024 | 9 | 15.035 → 10.888 | 12.874 / 11.966 / 12.062 | | 1024 | 1024 | 17 | 16.264 → 14.610 | 18.149 / 15.968 / 16.188 | | 1024 | 2048 | 9 | 18.041 → 15.920 | 21.786 / 20.282 / 20.458 | | 1024 | 2048 | 17 | 26.279 → 23.879 | 32.182 / 28.613 / 28.801 | | 2048 | 1024 | 9 | 27.187 → 18.500 | 20.663 / 19.135 / 19.234 | | 2048 | 1024 | 17 | 28.614 → 25.400 | 29.040 / 25.962 / 26.176 | | 2048 | 2048 | 9 | 31.466 → 27.515 | 34.251 / 32.346 / 32.446 | | 2048 | 2048 | 17 | 48.462 → 42.877 | 51.977 / 45.898 / 46.270 | | 4096 | 1024 | 9 | 49.654 → 32.181 | 30.966 / 29.015 / 29.088 | | 4096 | 1024 | 17 | 53.387 → 46.004 | 50.201 / 45.097 / 45.371 | | 4096 | 2048 | 9 | 57.550 → 50.024 | 53.390 / 50.104 / 50.318 | | 4096 | 2048 | 17 | 91.847 → 79.396 | 90.444 / 80.277 / 80.838 | The local 12.8 compiler **did not reproduce** the reported 79-register/3-CTA window allocation: unhinted and hinted window kernels both use 64 registers/4 CTAs here. The selective hint is retained as a portability cap for the reviewer's newer-toolchain result, with its local timing tradeoff shown rather than hidden. These kernel-only measurements do not attribute the older hybrid end-to-end gains below to the later narrow-tile commit. <details> <summary>Historical measurements and qualification evidence (not current-head acceptance)</summary> 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. The following results include the companion GenAI runtime and hybrid package, not just this PR's native kernel changes. They use the original pinned binaries and package hashes below, not the current rebased ORT head. **Unprofiled frozen real30, six H100s, two reversed same-GPU passes, 240 complete measured generations; original warmups, mode order, EOS/512 cap.** | Actual input tokens | Before ordinary tok/s | Hybrid ordinary tok/s | Gain | Original R8/k7 tok/s | |---|---:|---:|---:|---:| | 178-254 | 94.40 | 119.95 | +27.1% | 361.46 → 361.57 | | 427-932 | 94.01 | 119.59 | +27.2% | 298.68 → 298.94 | | 1028-1663 | 93.89 | 118.90 | +26.6% | 324.25 → 324.31 | Ordinary TTFT medians: short 357.35→359.00ms, medium 826.97→831.29ms, long 2153.15→2161.92ms. The earlier static-R1 version's prefill regression is **not** the package being qualified here. Separate same-GPU synthetic-2048 CUDA profiles, 64 captured target passes: IQ2 expert work **3.259→1.496ms/pass**, Mamba **0.824→0.423ms/pass**. These are device-work attribution, not an additional throughput claim. **Correctness:** all240 exact same-mode sequences and complete counters match; 388 complete live committed-state boundaries (66.43GB compared), capture off/on, two resets, prefix through130; original R8 ordinary/k7 retains1782 complete finite tensor hashes. Three native kernel tests, seven Mamba operator tests, fifteen GenAI tests execute without skips. The new replay test also passes CUDA memcheck with zero errors (100 repetitions). **Scope:** hybrid is ordinary-only. Both speculative arms use the original R8 package. The benchmark explicitly keeps two per-mode models resident in each arm; it is not a unified hybrid-speculative package or a k7 speedup. No precision/cache/mask workaround, no weight repack, no independent HF rerun, no clean-build/full-CI claim. Reproduce the exact tested graph/config with: ```bash python examples/python/nemotron-bolt-hybrid.py --input <packed-r8> --output <fresh-same-filesystem-hybrid> ``` Requires onnx-ir/numpy/ml-dtypes and both updated runtimes. External-data validation stays enabled; payloads are hardlinked inside the output package, not copied. Pins: - ORT: `0357a7dfe47d3c383bf36be62015162b6a612d5e` - Compiled/common GenAI: `d73a6e627d6d20a5a1688b9fbd46237069a7be89` - Published GenAI: `db6ffd29fc96e319f645ff461efa05c643235f29` (converter/docs-only child) - CUDA provider: `fac33c75d0336236736aa96456268057b628d93d0b9901d49598e275bf335275` - GenAI shared library: `f977660a408bc0a01a31151c7280282ba443fa256785680ae3e841654eec9be7` - Tested hybrid graph: `aaf5d6ae06b6740ab5b3af523359581930d2b6c42c38a18529a22737c2cfe530` - Config: `77f2d920d2b04e17884c3d2ee691d9053225b957c047454ebd0a4ea3649dac44` - Unchanged packed payload: `06d3d508e8d11235d0b770484b6b59764c2f297c3383b6d0de75648d26c11867` Full commands, per-case exact tokens/counters, raw kernel traces, provider maps, UUID/admission receipts, and rejection evidence remain on the validation host under `/opt/bolt-runtime-fixes-20261108-v1/evidence/ordinary-r1-v1`. Sealed manifest SHA256: `412b3898f09565557b01e82906358f017f9df3227db2bf330850245a52d32bbc`. Root-disk binaries were reloaded and verified with full ordinary/k7 generation; the large model payload still resides on the existing tmpfs, not reboot-persistent. Original package/deployment untouched; no merge. </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) --------- 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
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

Description
Adds
com.microsoft::Mamba2Verifyversion 1 (CUDA), a snapshot-aware Mamba2 operatorfor Nemotron Bolt. Fuses causal convolution, selective recurrence, and gated grouped
RMS normalization. A device INT32 selector chooses the starting snapshot; each
processed token writes its post-token convolution and SSM snapshots so the caller
can select the accepted/final state on the next invocation.
The retained contract uses BF16 activations/convolution, FP32 recurrent state,
readout and normalization coefficients, head_dim=64, d_state=128, and 1-16 token
rows. It preserves state aliasing, trailing snapshots, eight-row specialization,
and invalid-selector non-finite output behavior. Longer prefills require chunking.
This layer adds no projection, routing, or expert operator and requires no custom-op plugin.
Dependency: #33963 in
native stack #33967;
the eventual landing target is
main. The slot-aware single-row replay readout contract is included in this introducing layer.Summary of Changes
Schema and Kernel Registration
onnxruntime/core/graph/contrib_ops/fused_state_space_defs.honnxruntime/core/graph/contrib_ops/contrib_defs.cc, onnxruntime/contrib_ops/cuda/cuda_contrib_kernels.ccImplementation, Tests, and Documentation
onnxruntime/contrib_ops/cuda/sequence/fused_state_space.cconnxruntime/contrib_ops/cuda/sequence/fused_state_space_impl.{cu,h}onnxruntime/test/contrib_ops/fused_state_space_op_test.cc, onnxruntime/test/contrib_ops/cuda_kernels/fused_state_space_test.ccdocs/contrib_ops/cuda/mamba2_verify.md, docs/ContribOperators.md, docs/OperatorKernels.mdTesting
Optional-output update -
3e40c0d4380572c4edd2aaf47b32883437bba418xbc(output 3) andreadout(output 4) are independently optional; omittedintermediates use stream-aware ORT scratch workspace. Required outputs and all
existing output positions are unchanged.
remains
[slots, heads, d_state, head_dim]. CUDA math, dtypes/cast boundaries,timestep clamping, state selection and the readout/replay guarantee are unchanged.
plus one fresh-kernel/schema guard: 20 checks, zero failures/skips, on H100.
Profiles record 66
CUDAExecutionProvider/Mamba2Verifynode executions.output-3 placeholder; state aliases, lower/upper invalid selectors and
trailing/no-trailing snapshots. Eight capture cases (four combinations at
one/eight rows) verify actual graph capture and bitwise replay.
USE_CUDAandrun with
CUDA_VISIBLE_DEVICESempty; zero failures/skips.scoped official schema/kernel documentation rendering. The kernel-table row
remains unchanged; generated schema documentation shows 3-5 outputs.
Qualification freshly compiles the operator host/device code, schema and tests
against ABI-matched retained ORT 1.32.0 infrastructure. It is not a clean
full-source build, full-CI approval, independent HF parity or full-model acceptance.
The initial mixed-infrastructure-header harness failure was diagnosed in
OpTester::BuildModeland preserved; no production workaround or thresholdrelaxation was introduced. CUDA math/internal-test sources are byte-unchanged.
Historical validation before the optional-output update
Review-fix snapshot:
4f2bd30fe1f3017213ce9eb620b34ab507f5e392.Fixed static rank/dimension validation with CPU-only schema tests, dt clamp/large-dt and NaN behavior, strict BF16 ULP/fraction checking and nonuniform 1024-wide normalization. The slot-aware replay correction and
MambaSingleRowReplayPreservesMultiRowReadoutregression are now owned by this introducing PR (moved from #34003), with both host references updated and the single-slot path preserved. The permanent contract is nowdocs/contrib_ops/cuda/mamba2_verify.md.Owning-layer validation: 8 provider + 3 CPU schema + 4 actual internal CUDA gtests; 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.
Historical source provenance moved out of permanent documentation
Origin: #33940, commit
491dc043952066267b2212ba979f0325da318573, frozen external sourceexport-nemotron-pr-20261030/src/bolt_ops.cu, SHA2561f587d9eacc356805c37d19e94e7aa4465dd50302576b2ca4b9579d7c5ae8ba5. This identifies the original retained implementation, not a dependency in the merged tree or a promise that later dispatch fixes are absent. The slot-aware replay correction and current contract are documented in this PR and the permanent operator documentation. This is the Bolt precision contract, not independent HuggingFace model parity.Historical measurements and qualification evidence (not current-head acceptance)
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.
Measured CUDA kernel latency - 2026-11-07
BF16 projection/convolution, FP32 SSM state; 128 heads, eight groups, head dimension 64, state size 128, channels 10240, projection stride 18560, four-tap convolution. One fused R-row production launch is compared with R serial single-row production calls with exact state handoff; every timed invocation starts from the same immutable initial state. This compares three fused kernels with 3*R serial kernels.
Frozen Bolt precision contract: FP32 gate/normalization/gamma followed by BF16 output; this is not an acceptance test for the earlier Lightning cast-before-gamma contract. Conv snapshots, SSM snapshots and xBC are bitwise equal for all three cases in both runs. Y/readout pass normalized RMSE <=0.03 and cosine >=0.999; exact raw metrics are below. The one-row control is approximately unchanged; eight/sixteen-row fusion reduces latency.
H100 80GB HBM3, CUDA 12.8.93, driver 580.159.04, GCC 11.4.0. CUDA-event median per dispatch; 64 dispatches per captured CUDA graph, 50 warmups, three graph warmups, and 15 paired timed batches alternating AB/BA. Four rotating allocation banks contain deterministic synthetic weights (seed 617); this is not a cold-cache guarantee or a checkpoint-weight benchmark. Raw p95 values describe batch-average latency, not individual-invocation tails. No profiler runs in the timing window. The assigned GPU had empty admission, one stable compute client during execution, and clean release afterward; clocks were not locked. Two independent 39-case runs passed, including the published replay runner.
Scope: same-build production CUDA dispatch alternatives, not historical parent-commit binaries. The measured runtime is an isolated CUDA provider relink with preserved core/support, not a clean full-source ORT build or end-to-end model qualification. Each measured operator's CUDA source hash matches its owning PR head. A clean source build is a separate replication variant and must be measured again. Kernel-only timings do not establish model TTFT/tok/s, MMLU/LCB, speculative integration, or full-model readiness.
Complete primary/repeat results, numerical metrics, source hashes and benchmark code. All 39 cases passed in both supervised runs; full-model work remains paused. No source push, stack change, merge, auto-merge or ready-for-review promotion is included.
Checklist