Skip to content

fix(engine): honor native CUDA KV capacity - #770

Merged
justinchuby merged 2 commits into
mainfrom
squad/glm-native-kv-capacity
Aug 11, 2026
Merged

justinchuby merged 2 commits into
mainfrom
squad/glm-native-kv-capacity

Conversation

@justinchuby

Copy link
Copy Markdown
Owner

Summary

  • use native CUDA runtime KV hard max before metadata max_sequence_length for reservation
  • documents GLM/DeepSeek native load-gap investigation

Validation

  • CUDA_VISIBLE_DEVICES=2 cargo test -p onnx-genai-engine --features native-backend,cuda native_kv_reservation -- --nocapture
  • ONNX_GENAI_CUDA_KV_MAX_LEN=4096 ONNX_GENAI_GLM4_9B_CUDA_DIR=/home/justinchu/glm-e2e-artifacts/glm-4-9b-int4-cuda CUDA_VISIBLE_DEVICES=2 cargo test -q -p onnx-genai-engine --features native-backend,cuda --test glm4_9b_decode_lock -- --ignored --nocapture

GLM native CUDA token stream: [11, 358, 1079, 264, 220, 18, 6498, 1042].

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
justinchuby enabled auto-merge (squash) August 11, 2026 04:19
@codecov

codecov Bot commented Aug 11, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.04%. Comparing base (1179f7b) to head (1b09e2b).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            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     
Flag Coverage Δ
cli-ort-linux 83.41% <ø> (ø)
cli-ort-windows 82.90% <ø> (ø)
mlas ?
offline 79.91% <ø> (+0.18%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 5 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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>
@justinchuby
justinchuby merged commit 67fed56 into main Aug 11, 2026
12 of 15 checks passed
@justinchuby
justinchuby deleted the squad/glm-native-kv-capacity branch August 11, 2026 04:43
@github-actions

Copy link
Copy Markdown

⚠️ Benchmark Change Detected

Comparison of criterion micro-benchmarks: PR head vs merge-base, measured on the same runner in the same job (base first → PR second).

ℹ️ Absolute times are informational only — they vary with runner load. The % change column is the reliable signal because both sides ran under identical conditions.

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: ⚠️ ≥ 15% slower, 🔴 ≥ 30% slower — calibrated against measured runner noise (~27% worst-case on multi-threaded matmul)

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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant