Repository navigation
fix(engine): honor native CUDA KV capacity - #770
Merged
Merged
Conversation
Use the runtime CUDA KV hard maximum for native KV reservation before falling back to the model metadata max context. This lets long-context GLM exports load when the session is intentionally capped for decode/profiling. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
justinchuby
enabled auto-merge (squash)
August 11, 2026 04:19
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #770 +/- ##
==========================================
+ Coverage 79.88% 80.04% +0.16%
==========================================
Files 331 329 -2
Lines 137462 135292 -2170
Branches 137462 135292 -2170
==========================================
- Hits 109812 108298 -1514
+ Misses 23306 22662 -644
+ Partials 4344 4332 -12
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
Treat usize::MAX CUDA KV capacity as unbounded rather than reservable so models without a declared max context retain the warning-and-load behavior. Keep finite runtime caps preferred over metadata. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
| Status | Scenario | Base | PR | Change |
|---|---|---|---|---|
gather/large_bf16_threads=1-internal/131072 |
14.59 µs | 16.90 µs | +15.8% | |
| ✅ | gather/large_f16_threads=1-internal/131072 |
14.49 µs | 16.54 µs | +14.2% |
| ✅ | gather/large_f32_threads=1-internal/131072 |
35.86 µs | 40.68 µs | +13.4% |
| ✅ | matmul/large_generic_f16_threads=8/32x1024x1024 |
104.10 µs | 109.84 µs | +5.5% |
| ✅ | matmul/large_generic_bf16_threads=1/32x1024x1024 |
2.03 ms | 2.12 ms | +4.5% |
| ✅ | qwen3_sampling_processors/top_k_partial_selection |
147.30 µs | 152.52 µs | +3.5% |
| ✅ | qwen3_sampling_processors/top_p_full_sort_after_top_k_baseline |
3.55 ms | 3.67 ms | +3.4% |
| ✅ | block_quantized_matmul_cached_dense/mxfp4_cached_dense_repeated_call/1x1024x1024 |
134.09 µs | 138.26 µs | +3.1% |
| ✅ | matmul/large_generic_f32_threads=1/32x1024x1024 |
9.89 ms | 10.19 ms | +3.0% |
| ✅ | matmul/medium_generic_f32_threads=8/32x512x512 |
1.94 ms | 1.98 ms | +2.5% |
| ✅ | block_quantized_matmul_cached_dense/mxfp4_uncached_dequant_each_call/1x1024x1024 |
1.31 ms | 1.35 ms | +2.4% |
| ✅ | matmul/medium_generic_f32_threads=1/32x512x512 |
2.54 ms | 2.58 ms | +1.7% |
| ✅ | block_quantized_matmul_cached_dense/mxfp4_preexpanded_dense_oncelock_like_proxy/1x1024x1024 |
109.39 µs | 110.94 µs | +1.4% |
| ✅ | tokenization/decode_tokens_per_second |
6.70 ms | 6.79 ms | +1.4% |
| ✅ | qwen3_sampling_processors/top_k_top_p_full_sort_baseline |
5.86 ms | 5.93 ms | +1.2% |
| ✅ | matmul/small_generic_bf16_threads=8/1x256x256 |
38.35 µs | 38.79 µs | +1.1% |
| ✅ | block_quantized_moe_cached_dense/mxfp4_cached_dense_expert_repeated_call/rows=1,H=256,I=256,E=4,top_k=1 |
77.71 µs | 78.32 µs | +0.8% |
| ✅ | sampling_latency/min_p_per_token |
214.50 µs | 213.84 µs | -0.3% |
| ✅ | sampling_latency/top_k_per_token |
54.29 µs | 54.11 µs | -0.3% |
| ✅ | matmul/large_generic_f32_threads=8/32x1024x1024 |
7.58 ms | 7.54 ms | -0.4% |
| ✅ | qwen3_sampling_processors/top_k_top_p_fast |
673.86 µs | 670.69 µs | -0.5% |
| ✅ | matmul/medium_generic_bf16_threads=1/32x512x512 |
549.49 µs | 545.78 µs | -0.7% |
| ✅ | gather/medium_bf16_threads=1-internal/32768 |
2.45 µs | 2.43 µs | -1.0% |
| ✅ | matmul/small_generic_bf16_threads=1/1x256x256 |
38.66 µs | 38.13 µs | -1.4% |
| ✅ | qwen3_sampling_processors/top_k_full_sort_baseline |
2.19 ms | 2.16 ms | -1.6% |
| ✅ | matmul/medium_generic_f16_threads=1/32x512x512 |
40.28 µs | 39.59 µs | -1.7% |
| ✅ | matmul/small_generic_f16_threads=1/1x256x256 |
39.69 µs | 38.99 µs | -1.7% |
| ✅ | matmul/large_generic_bf16_threads=8/32x1024x1024 |
2.45 ms | 2.39 ms | -2.5% |
| ✅ | matmul/medium_generic_bf16_threads=8/32x512x512 |
660.97 µs | 644.50 µs | -2.5% |
| ✅ | grammar_masking/llguidance_compute_mask/32 |
82.97 µs | 80.76 µs | -2.7% |
| ✅ | gather/small_f32_threads=1-internal/4096 |
694.5 ns | 675.9 ns | -2.7% |
| ✅ | kv_cache/alloc_dealloc_pages |
42.48 µs | 41.28 µs | -2.8% |
| ✅ | sampling_latency/greedy_per_token |
3.39 µs | 3.29 µs | -3.1% |
| ✅ | logit_processing/seven_processor_chain_per_step |
339.10 µs | 327.98 µs | -3.3% |
| ✅ | qwen3_sampling_processors/top_p_fast_after_top_k |
546.02 µs | 527.95 µs | -3.3% |
| ✅ | matmul/medium_generic_f16_threads=8/32x512x512 |
43.76 µs | 42.26 µs | -3.4% |
| ✅ | block_quantized_moe_cached_dense/mxfp4_uncached_expert_dequant_each_call/rows=1,H=256,I=256,E=4,top_k=1 |
582.33 µs | 560.54 µs | -3.7% |
| ✅ | matmul/small_generic_f16_threads=8/1x256x256 |
38.99 µs | 37.32 µs | -4.3% |
| ✅ | matmul/large_generic_f16_threads=1/32x1024x1024 |
91.24 µs | 86.99 µs | -4.7% |
| ✅ | sampling_latency/top_p_per_token |
407.89 µs | 381.07 µs | -6.6% |
| ✅ | matmul/small_generic_f32_threads=1/1x256x256 |
50.25 µs | 46.90 µs | -6.7% |
| ✅ | matmul/small_generic_f32_threads=8/1x256x256 |
55.30 µs | 50.13 µs | -9.3% |
| ✅ | add/medium_f16_threads=1-internal/262144 |
2.99 ms | 2.58 ms | -13.5% |
| ✅ | add/medium_bf16_threads=1-internal/262144 |
3.06 ms | 2.64 ms | -13.6% |
| ✅ | gather/medium_f32_threads=1-internal/32768 |
4.64 µs | 3.95 µs | -14.8% |
| 🟢 | add/small_bf16_threads=1-internal/1024 |
15.33 µs | 12.89 µs | -15.9% |
| 🟢 | gather/small_f16_threads=1-internal/4096 |
594.3 ns | 499.1 ns | -16.0% |
| 🟢 | add/medium_f32_threads=1-internal/262144 |
3.07 ms | 2.53 ms | -17.6% |
| 🟢 | add/large_f16_threads=1-internal/4194304 |
52.51 ms | 42.90 ms | -18.3% |
| 🟢 | tokenization/encode_tokens_per_second |
478.23 µs | 381.62 µs | -20.2% |
| 🟢 | add/small_f32_threads=1-internal/1024 |
267.0 ns | 212.1 ns | -20.6% |
| 🟢 | reduce_mean/small_f32_threads=1-internal/4096 |
19.37 µs | 15.36 µs | -20.7% |
| 🟢 | add/small_f16_threads=1-internal/1024 |
16.98 µs | 13.22 µs | -22.2% |
| 🟢 | add/large_f32_threads=1-internal/4194304 |
52.26 ms | 40.65 ms | -22.2% |
| 🟢 | gather/small_bf16_threads=1-internal/4096 |
622.4 ns | 483.2 ns | -22.4% |
| 🟢 | add/large_bf16_threads=1-internal/4194304 |
55.51 ms | 42.80 ms | -22.9% |
| 🟢 | reduce_mean/large_f32_threads=1-internal/262144 |
1.33 ms | 997.50 µs | -24.7% |
| 🟢 | gather/medium_f16_threads=1-internal/32768 |
3.33 µs | 2.41 µs | -27.5% |
| 🟢 | reduce_mean/medium_f32_threads=1-internal/65536 |
363.12 µs | 248.10 µs | -31.7% |
Visual flags:
Host info
CPU: Apple M1 (Virtual)
Cores: 3
OS: Darwin 25.5.0 arm64
Rust: rustc 1.97.1 (8bab26f4f 2026-07-14)
Load avg: { 3.45 3.42 6.01 }
What this cannot catch
- Regressions in code paths not covered by these benchmarks (e.g., end-to-end decode with a real model)
- Sub-threshold regressions that compound over multiple PRs
- Performance changes that only manifest under GPU execution
- Latency changes in the ORT integration path (these benchmarks exercise the native Rust kernels)
justinchuby
added a commit
that referenced
this pull request
Aug 11, 2026
## Summary - gate the native KV reservation helper behind `native-backend` - gate the four helper-specific unit tests the same way - fixes ORT-only CLI clippy dead_code from #770/#771 ## Validation - Reproduced before fix: `cargo clippy --locked -p onnx-genai-cli --all-targets -- -D warnings` failed with dead_code on `native_kv_reservation_max_context` - After fix: `cargo clippy --locked -p onnx-genai-cli --all-targets -- -D warnings` - After fix: `cargo clippy --locked -p onnx-genai-engine --no-default-features --features cuda-13000 -- -D warnings` - After fix: `CUDA_VISIBLE_DEVICES=2 LD_LIBRARY_PATH=/home/tlwu/cudnn9.19_cuda13/lib:$LD_LIBRARY_PATH cargo clippy -p onnx-genai-engine --features "cuda native-backend" -- -D warnings` - `cargo fmt --all` Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
justinchuby
added a commit
that referenced
this pull request
Aug 11, 2026
…-27B native CUDA (#779) ## Summary Enables **Qwen/Qwen3.6-27B** (`model_type: qwen3_5`, hybrid GDN `LinearAttention`/`CausalConvWithState` + periodic `GroupQueryAttention` + int4 `MatMulNBits`) to load and decode on the **native CUDA EP**, byte-exact vs an fp32 oracle. This was the last model the ORT-vs-native benchmark flagged as _"Unsupported native load: model needs unsupported native operators"_. ## Root cause (not a kernel gap, not a bad graph) The 27B `model.onnx` is a **correct** hybrid graph — 64 layers = 48 GDN linear-attention layers (`conv_state`/`recurrent_state`) + 16 periodic full-attention layers (dense `key`/`value`) — and the native kernels already exist. The blocker is the artifact's **thin `inference_metadata.yaml`**: it declares only `grouped_query_attention` and **no `io` port contract**. On the native load path the Resource Governor derives per-layer KV page byte geometry from `model.io.kv_inputs`/`kv_outputs`; with no `io` block `resolve_kv_layers` returns `None` (it deliberately never guesses KV pairing from tensor names), so load failed with `cannot derive the KV memory budget because per-layer KV page geometry is unknown`. ## Fix (DRY, attribute/shape-driven — no model-name gate) The native loader now auto-derives the decoder `io` port contract from the ONNX graph's own port inventory when the sidecar declares none, via `GenAiConfig::derive_decoder_io_from_graph` — the exact proven derivation the native decode step driver already uses in `derive_fallback_io`. New helper `maybe_fill_hybrid_io_from_graph` (`engine/load.rs`) fills the sparse dense `kv_inputs`/`kv_outputs` + fixed recurrent `state_pairs` (and token/mask/ position/logits port names by presence). It is gated on a non-empty derived `state_pairs` (the recurrent-hybrid case shape inference cannot classify); a declared `io` block always wins and pure-dense decoders are untouched. Added `Default` to `ModelCapabilities` so the derived spec can attach when `model` is absent. This makes **all** future hybrid GDN models with a correct graph but thin metadata auto-run the optimal native path. ## Validation (H200) - Native-CUDA fp16 greedy of `"The capital of France is"` → `[11751, 13, 271, 248068, 271, 248069, 271, 4639]` = `" Paris.\n\n<think>\n\n</think>\n\nThat"` (coherent). - Teacher-forced next token (fresh engine): native-CUDA fp16 = **11751** " Paris" (logprob −0.6080). - **fp32 oracle** (fp16→fp32 up-conversion, int4 preserved, native CPU) teacher-forced argmax = **11751** " Paris" (logprob −0.6100, top-1 margin **2.549** nats). Byte-exact parity ✅ — fp16/fp32 logits near-identical. Locked by `crates/onnx-genai-engine/tests/qwen35_27b_hybrid_native_cuda_e2e.rs` (ignored; env `QWEN35_27B_DIR`, `QWEN35_27B_FP32_ORACLE_DIR`), mirroring the 35B QMoE oracle lock. 🤖 Working as Cohaagen (native-model-enablement). Follows the GLM (#770) / DeepSeek-V2-Lite (#771) playbook. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
justinchuby
added a commit
that referenced
this pull request
Aug 12, 2026
…detail (#825) Justin asked to update `docs/PROGRESS.md` with the latest progress and drop stale info. It had grown to **1166 lines** of day-by-day changelog spanning 2026-07-15 → 2026-07-27, with the entire recent arc missing. ## Changes (1166 → 303 lines) - **Added recent milestones (2026-07-28 → 2026-08-12), newest-first:** - EP plugins run inside ORT via the plugin-EP C ABI (#762) and ship on PyPI — **`nxrt-ep-cpu` + `nxrt-ep-cuda` 0.1.0.dev5 both LIVE** (#819/#824/#820). - Absent-optional-output memory-safety wave (#762 review; Miri-clean). - VMM / KV-layout / offload / batching residency wave — managed no-spill VMM default, layout-governed KV floor (768× reduction), offload+capture coexist, #736 over-reservation audit (#755–#814). - Issue triage + autonomous fixes (#784/#785/#786/#788/#789); CPU-EP TopK correctness+perf (#774/#775). - Qwen3.5/3.6-27B hybrid Gated-DeltaNet native CUDA (#779); GLM-4-9B + DeepSeek-V2-Lite native + ORT 1.28 3-config fairness (#766/#770/#771). - Fused QMoE decode kernel + QMoE arc concluded; CUDA-graph capture trilogy, version-selectable CUDA (#708/#728/#757/#760), megakernel study (#769). - **Compressed stale detail:** the ~40 dated July day-by-day sections + verbose diffusion/LoRA/ORT2 narrative collapsed into a ~35-line "Foundational milestones" spine; superseded perf-wave numbers dropped; §1–§40 table condensed to a compact grid. - **Header refreshed:** last-updated → 2026-08-12; Published line now lists both EP plugins on PyPI + Miri CI. - **Preserved & updated** the DeepSeek/GLM known-gaps checklists and added new open items. Docs-only; full narrative remains in `.squad/decisions-archive/` and `docs/benchmarks/`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Validation
GLM native CUDA token stream: [11, 358, 1079, 264, 220, 18, 6498, 1042].