Repository navigation
perf(cuda-ep): close LinearAttention C2 capture seams - #757
Conversation
Guard supported kernel synchronizations during CUDA graph capture, make allocation-heavy paths advertise truthful capture support, and add recurrent-state and source-audit regressions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #757 +/- ##
==========================================
- Coverage 80.22% 79.36% -0.86%
==========================================
Files 331 331
Lines 137462 137462
Branches 137462 137462
==========================================
- Hits 110275 109093 -1182
- Misses 22844 24029 +1185
+ Partials 4343 4340 -3
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
🔴 Benchmark Regression DetectedComparison of criterion micro-benchmarks: PR head vs merge-base, measured on the same runner in the same job (base first → PR second).
Visual flags: Host infoWhat this cannot catch
|
The honesty checker requires every integration test under the CUDA test
directories to be #[ignore]d so a CPU-only runner cannot silently 'pass'
a GPU test. capture_sync_contract is not a GPU test: it is a static source
audit that reads kernel sources and fails on any capture-unsafe
unconditional synchronize(). It touches no device and legitimately passes
on CPU, which tripped the checker ('executed without gpu-tests').
Add it to ALWAYS_RUN (the sanctioned 'checking the checker' allowlist,
alongside suite_canary_gpu) so the honesty checker no longer mis-polices
it, and add a dedicated CI step that runs the audit on the CPU lane so a
capture-unsafe sync still fails at PR time.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Handoff to the H200 teamThis PR is being handed to the H200 team to finish. Everything below is the What is establishedThe seam had a concrete, verified cause. Measured on this box, before the change: 34 segments, 33 This PR also audits every CUDA kernel synchronization for the same The gap — please close thisThe 35B-A3B end-to-end result is NOT measured. The expected outcome is a What still needs to run on hardware with the 35B-A3B artifacts:
What has been validated locally
Blast radiusThis touches the trailing-sync behavior of several shared kernels, so a wrong Context worth carrying overWeight offload and CUDA graph capture are currently mutually exclusive |
Resolve conflicts in executor/bindings.rs and kernels/attention.rs. bindings.rs (vs #751): centralise governed-node detection in is_planned_workspace_node, extended to cover BlockQuantizedMoE, IndexShare and com.microsoft::Attention Phase-2a, with per-lifetime-class workspace peaks preserved. attention.rs (vs #757): keep the use_fused helper shared by planning and execution while preserving the capture-safe store and Phase-2a capture refusal so capture_support stays truthful and capture_sync_contract holds. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…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>
Summary
C2 follow-up to #728. This closes the capture-contract bug behind its 33 residual LinearAttention seams and audits the rest of the CUDA kernel directory for the same class of violation.
Established mechanism
A direct capture of
LinearAttentionKernel::executereproduced the failure before this change:The unconditional trailing
synchronize()aborted recording. Session quarantine then classified every sibling LinearAttention node asCaptureRecordingFailed.CaptureRecordingFailedBecause #728's complete seam census was exactly those 33 LinearAttention nodes, the deterministic expected result on the same artifact is 34 → 1 segment. I am not presenting that as measured: the required 35B artifacts are absent here and the available GPU is an 8 GB RTX 4060.
Why the synchronization is not load-bearing
LinearAttention launches one kernel on the executor stream and performs no host readback or second-stream work. Native decode deliberately aliases past/present recurrent state, but each thread loads its full state column before overwriting it. The new regression captures and replays four changing decode steps with that aliasing and verifies output plus recurrent state byte-for-byte against eager CUDA. The sync is therefore only eager asynchronous-error surfacing; same-stream ordering supplies visibility during capture.
CUDA kernel audit
Capture-aware trailing synchronization:
structural.rs)Truthful/dynamic admission for allocation or host-staged paths:
capture_sync_contract.rssource-audits every kernel synchronization and fails on any new unreviewed unconditional sync reachable by a capture-supported path. Intentional unsupported/fallback sites are explicitly allowlisted. No assertions were added toDrop.Validation
Passed locally with the requested CUDA wheel paths, including cuBLASLt:
cargo fmt --all -- --checkcargo clippy -p onnx-runtime-ep-cuda --features cuda -- -D warningscargo clippy --locked --all-targets -p onnx-genai-engine --features native-backend -- -D warningslinear_attention_gpu: 7 passedattention_gpu: 5 passed, 1 benchmark ignoredPure-attention
qwen2.5-0.5b-int4-onnx-nativeproduced byte-identical 64-token output with capture off/on:The re-anchored 35B oracle binaries compiled and were invoked with
ONNX_GENAI_CUDA_GRAPH=0and=1; both real-model cases skipped because/home/justinchu/qwen36-35b-a3b-qmoe-artifactsis unavailable. The same-artifact 34 → 1 segment measurement and 35B oracle run are required before merge.