Repository navigation
refactor: name the two CUDA paths instead of calling both of them cuda - #1629
Merged
Merged
Conversation
The word `cuda` meant two opposite things one crate boundary apart. The CLI's
`cuda` selected ONNX Runtime's CUDA EP; the server's `cuda` selected ours, and
the CLI's `cuda` was wired to the server's `ort-cuda`. Picking the one that
sounds right gave a binary with none of this repo's kernels in it, which reads
as a 22x regression in whatever you last edited rather than as a wrong build.
That is Trap 7 in the perf skill; it was written down because it cost real
measurement time.
Every crate that offers a choice now names the choice:
ort-cuda ONNX Runtime's CUDAExecutionProvider
native-cuda our `onnx-runtime-ep-cuda`, a strict superset of ort-cuda
Crates with only one CUDA path (`onnx-genai`, `onnx-genai-ort`,
`onnx-runtime-session`, `onnx-runtime-ep-cuda`, `onnx-runtime-python`) keep the
plain `cuda`, because there is nothing there to confuse it with. That rule, and
the feature matrix, are now written down in `docs/build-features.md`.
They are deliberately not merged. The CUDA wheels build these same crates with
`--features ort-cuda` precisely so no CUDA code is bundled and the wheel
builders need no CUDA toolkit; one merged `cuda` would force every wheel build
to compile our kernels.
`native-cuda` now also implies `native-backend`, which fixes a real trap rather
than just renaming one. `onnx-genai-server --features cuda` used to compile the
entire native CUDA EP and then leave out the native session that dispatches to
it, so the EP was present, unreachable, and the build behaved exactly like the
ORT one while looking like it should not. Same for `onnx-genai-engine`,
`onnx-genai-bench` and `onnx-genai-capi`. capi in particular has zero references
to `onnx-runtime-ep-cuda`, so it was imposing a CUDA toolkit on its build to
compile an EP nothing could call; it now forwards `ort-cuda`, which is what its
own comment already said it does.
Verification:
- 227 cfgs renamed. 77 of them were `all(cuda, native-backend)` pairs, now
redundant and collapsed. `unexpected_cfgs` is on by default and reports the
legal values, so a missed rename cannot silently drop code -- confirmed
empirically against a deliberately bogus feature name, and every build below
reports `unexpected_cfg = 0`.
- All seven combinations compile: cli/server/bench x {native-cuda, ort-cuda},
plus capi ort-cuda.
- The names now match the binaries. `native-cuda` gives 129 `matmul_nbits_gemv`
symbols and 52 MB; `ort-cuda` gives 0 and 39 MB.
- Behaviourally equivalent to main: the `native-cuda` CLI built from this branch
and from main agree on symbol counts exactly (gemv 129/129, ep_cuda
3118/3118) and differ by 1952 bytes of embedded feature-name strings.
- onnx-genai-engine 588 passed / 0 failed, onnx-genai-server 246 / 0. Engine
gains 3 tests over main because `native-cuda` now pulls the backend those
tests need, which previously had to be asked for separately.
- End-to-end unchanged: p50 inter-token 23.4 ms. The ort-cuda binary starts.
- Clippy warning set is byte-identical to main's; nothing new introduced.
Call sites updated: wheels.yml, publish.yml, ci.yml, the perf skill's Trap 7,
the H200 and Windows runbooks, the bench and parity READMEs, and the parity
script. Dated benchmark records and `.squad` archives are left alone; they
record what was actually run at the time.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0190e2eb-abe4-451f-b36d-44a035a99b7e
justinchuby
added a commit
that referenced
this pull request
Aug 21, 2026
…dent ways (#1630) Found while sweeping for call sites the CUDA feature rename (#1629) might have invalidated. This script was already broken before that change, and would have been mistaken for fallout from it. Both failures are reproducible and neither is subtle: $ cargo build --release -p onnx-genai --bin onnx-genai --features cuda error: no bin target named `onnx-genai` in `onnx-genai` package The `onnx-genai` package ships only the diffusion bins (`run_comfyui`, `render_sd`). The CLI binary lives in `onnx-genai-cli`. The feature is now spelled `ort-cuda`, which is also what the script's own comment describes ("propagates to onnx-genai-ort/cuda"). $ onnx-genai generate --model DIR --max-new-tokens 4 "hi" error: unexpected argument '--model' found `generate` takes the model directory positionally; there is no `--model` flag. Verified: the corrected build line produces `target/release/onnx-genai`, and the corrected invocation gets past argument parsing into model loading (it fails on a deliberately absent directory with the package-inspection error, which is the next stage), while the old form is still rejected by clap. `bash -n` clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0190e2eb-abe4-451f-b36d-44a035a99b7e Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0190e2eb-abe4-451f-b36d-44a035a99b7e
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1629 +/- ##
==========================================
+ Coverage 80.85% 81.05% +0.20%
==========================================
Files 383 384 +1
Lines 175785 180225 +4440
Branches 175785 180225 +4440
==========================================
+ Hits 142137 146089 +3952
- Misses 28743 29193 +450
- Partials 4905 4943 +38
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
This was referenced Aug 21, 2026
justinchuby
added a commit
that referenced
this pull request
Aug 21, 2026
…p rotting (#1635) Answering "is everything broken fixed?" properly meant checking rather than recalling, so I validated every `cargo` command written down in the repo against `cargo metadata`. 262 commands; six named something that does not exist. Two were my own fallout from the feature rename (#1629), which I missed because I updated `.github/skills/` and not `.agents/skills/`: - `.agents/skills/profiling/SKILL.md` still asked for `bench-native,cuda`. - `crates/onnx-genai-capi/README.md` still asked for `--features cuda`. One is a shell script with exactly the two bugs I fixed in #1630, which I should have found then by looking at the class of defect instead of the instance: - `scripts/build_real_model.sh` built `-p onnx-genai --bin onnx-genai` (that package ships only the diffusion bins) and called `generate --model DIR` (the model directory is positional). Three predate all of this and are worse than stale -- they were never true: - `docs/ep-plugin/EP_PLUGIN_EXPORT_TEST_PLAN.md` built a `plugin-export` feature on `onnx-runtime-ep-cpu` and grepped for `CreateEpApiFactories`. What shipped is a separate `onnx-runtime-ep-cpu-plugin` cdylib exporting `CreateEpFactories` and `ReleaseEpFactory`. Verified by building it and reading `nm -D`. - `docs/performance/CPU_MATMUL_ASSIGNMENT.md` gave a repro recipe using a `bench_prec` binary with `--native-threads` / `--ort-intra-threads`. `git log` finds no commit that ever added or removed it. The recipe is removed rather than annotated, because a command that cannot run is not worth keeping; the section now says plainly that those numbers cannot be reproduced as written. - A fixture generator credited its canonical output to `cargo run -p onnx-std --example convert_fixture`. That example has never existed either. The reason all six survived is that nothing ever checks a command that nothing ever runs; the failure then looks like the reader's environment rather than the line. `scripts/check_documented_commands.py` now validates the parts that can be checked statically -- package, `--bin`, `--example`, `--test`, `--bench`, `--features` -- and runs in the `rust-quality` lane. Dated docs and `.squad` archives are skipped: they record what was run at the time. Verification: - The check reports 262 commands, all resolving, on this branch. - It has teeth, by the same `--self-test` convention the dispatch-manifest lint uses: six cases, five that must be detected (bad feature, bad bin, unknown package, bad bench, bad `dep/feature`) and one valid command that must stay silent. Also confirmed by hand against the real tree, by breaking `docs/build-features.md` and the profiling skill and watching each get caught. - `bash -n` clean on the repaired script, and its new CLI form reaches model loading instead of being rejected by clap. - `ci.yml` parses as YAML. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0190e2eb-abe4-451f-b36d-44a035a99b7e Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0190e2eb-abe4-451f-b36d-44a035a99b7e
justinchuby
added a commit
that referenced
this pull request
Aug 21, 2026
Main's #1629 renamed this crate's `cuda` feature to `native-cuda`. A stale `#[cfg(feature = "cuda")]` is not a compile error: an unknown feature simply evaluates false, so the rename would have silently switched the workflow island runner's device-memory sampling off on every CUDA build while the tree still compiled and every test still passed. Gate on `ort-cuda` instead. That is the feature that actually brings in `onnx-genai-ort/cuda`, where `cuda_rt::device_memory_info` lives, and `native-cuda` enables it transitively -- so the single condition covers both CUDA paths exactly, with no narrowing relative to the old disjunction. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Justin Chuby <justinchuby@users.noreply.github.com>
justinchuby
added a commit
that referenced
this pull request
Aug 21, 2026
Main's #1629 renamed this crate's `cuda` feature to `native-cuda`. A stale `#[cfg(feature = "cuda")]` is not a compile error: an unknown feature simply evaluates false, so the rename would have silently switched the workflow island runner's device-memory sampling off on every CUDA build while the tree still compiled and every test still passed. Gate on `ort-cuda` instead. That is the feature that actually brings in `onnx-genai-ort/cuda`, where `cuda_rt::device_memory_info` lives, and `native-cuda` enables it transitively -- so the single condition covers both CUDA paths exactly, with no narrowing relative to the old disjunction. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Justin Chuby <justinchuby@users.noreply.github.com>
justinchuby
added a commit
that referenced
this pull request
Aug 21, 2026
Main's #1635 added a lint that resolves every documented `cargo` command against the actual workspace, and it caught two real inconsistencies this branch had left behind. `crates/onnx-genai/src/bin/run_diffusion.rs` was deleted here in "Remove legacy composite pipeline execution", because it drove the strategy/phase composite runtime that `pipeline.workflow` replaces. Ten `scripts/*.py` helpers still shelled out to `target/release/run_diffusion` and told the reader to build it with `cargo build -p onnx-genai --bin run_diffusion`. None of them could run: the binary they exec cannot be built. Delete them with the runner they drive rather than leaving instructions that cannot be followed -- exactly the rot the new lint exists to prevent. Nothing outside the group references them; the only mentions are among themselves and in a dated decisions archive. Also point the workflow performance doc at `native-cuda`, since main's #1629 renamed the feature its example passed to `cargo test`. `scripts/check_documented_commands.py` now exits clean, as do the other quality-gate lints. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Justin Chuby <justinchuby@users.noreply.github.com>
justinchuby
added a commit
that referenced
this pull request
Aug 21, 2026
… hiding (#1632) Closes #1631. ## The gap No job in any workflow enabled `onnx-genai-engine`'s `native-cuda` feature. Three independent checks on `origin/main` (`f8eb8a3e2`): 1. **`native-cuda` appears in `ci.yml` exactly once — inside a comment** (line 838). There is no `--features native-cuda` anywhere. 2. **Nothing enables it transitively.** No `default` reaches it (`engine`, `cli`, `server`, `bench` all default to `["cuda-13000", …]`). Every other mention across `crates/*/Cargo.toml` is `required-features = ["native-cuda"]`, which *restricts* a target rather than enabling a feature, plus one forwarding entry in `onnx-genai-server`. 3. **The CUDA jobs do not build the engine.** They run `cargo check --locked -p onnx-runtime-ep-cuda -p onnx-runtime-python --features onnx-runtime-python/cuda` — no `-p onnx-genai-engine`. So roughly **167 `#[cfg(feature = "native-cuda")]` sites** — `native_decode/{mod,load,cuda,tensor,tests}.rs`, `memory_authority.rs`, `pipeline/*` — were never type-checked, linted, or tested. A change could break or orphan any of them with every check on the PR green. ## Why the usual safety net does not cover this `unexpected_cfgs` is warn-by-default and does fire, and `RUSTFLAGS: "-D warnings"` escalates it. But that protection is conditional on the code being **compiled**, so it inverts exactly where it is needed: | stale `feature = "cuda"` written… | compiled? | result | |---|---|---| | in ordinary engine code | yes | warns → **CI red** | | inside a `#[cfg(feature = "native-cuda")]` block | **no** | never linted → **CI green** | The CUDA code is by definition inside those blocks. Worth noting separately that `-D warnings` is set on only four jobs (`Fast (Linux x86_64)`, `Rust coverage (*)`, `Rust (Windows ARM64)`, `EP conformance`) and on **neither** `CUDA compile` job, so this step carries `-- -D warnings` on the invocation itself rather than relying on job env. ## It was already broken Not a hypothetical. `main` fails the command today: ``` $ cargo clippy --locked -p onnx-genai-engine --features native-cuda --all-targets -- -D warnings error: method `kv_commits_on_demand` is never used --> crates/onnx-genai-engine/src/native_decode/cuda.rs:3005:19 = note: `-D dead-code` implied by `-D warnings` exit=101 ``` `kv_commits_on_demand` exists only so a regression test can assert the VMM path is genuinely being exercised, and its **only caller is inside a `#[cfg(test)]` module** — so in the plain `lib` target it is really dead. It is `pub(crate)`, so no integration test outside the crate could reach it either. I gated it on `test` as well as the feature, which states that intent, rather than reaching for `#[allow(dead_code)]` which would only silence the report. This also shows why `--all-targets` is load-bearing: `--lib` alone does not surface this class of defect, and `--lib` is exactly what someone verifying by hand would reach for. ## Verification All under the pinned 1.98.0. **Negative control on a clean worktree of `origin/main`:** | tree | exit | |---|---| | `origin/main` (`f8eb8a3e2`) | **101** — `-D dead-code` | | this branch | **0** | **The lane can actually fail** — the acceptance criterion from #1631 and #1621, since a new check that is green on day one proves nothing about whether it is wired correctly. I injected the exact mistake this is meant to catch, a stale feature name inside a `native-cuda` module: ``` +#[cfg(feature = "cuda")] +fn injected_stale_feature_probe() -> bool { true } ``` ``` error: unexpected `cfg` condition value: `cuda` error: could not compile `onnx-genai-engine` (lib) due to 1 previous error exit=101 ``` Injection reverted and the tree re-verified at exit 0. So a botched `cuda` → `native-cuda` rename is now caught, where before it would have compiled to `false` silently. **No collateral damage:** `cargo fmt --all -- --check` clean; `cargo test --locked -p onnx-genai-engine --features native-backend --lib` → **568 passed, 0 failed**, identical to `main`. **Cost:** check-only. CUDA is dynamically loaded, so no GPU and no CUDA toolkit — the same premise the neighbouring `Clippy CUDA execution provider` step already relies on. It runs in the existing `CUDA compile (Linux x86_64)` job rather than adding one, so no new runner is provisioned. ## What I could not verify - **The step is Linux-only.** Any Windows-specific `cfg` inside the `native-cuda` blocks stays uncovered. I chose not to double the cost on a first pass; if that surface is real it should be a follow-up rather than assumed covered. - **This is compile coverage, not test coverage.** The CUDA integration tests remain behind `required-features = ["native-cuda"]` and are still not run — they need a GPU runner. This closes "the code is never compiled", not "the code is never exercised". - **I did not audit the other three renamed crates** (`cli`, `server`, `bench`) for the same gap; they also define `native-cuda` and may have their own uncompiled surface. ## Note on #1629 To be fair to it: its `cuda` → `native-cuda` rename is **clean** — zero lingering `feature = "cuda"` references in any of the four renamed crates. This PR is about the gap that rename exposed, not a defect in it. The rename is also **partial by design**: four crates use `native-cuda` while nine still define `cuda` (`onnx-runtime-ep-cuda`, `onnx-genai-ort`, `onnx-runtime-session`, …), so "which name does this crate use" cannot be answered from memory — and until this PR, guessing wrong inside CUDA code was invisible. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 08760f2f-160f-41e5-828d-9d9b6045c00d
justinchuby
added a commit
that referenced
this pull request
Aug 21, 2026
Main's #1629 renamed this crate's `cuda` feature to `native-cuda`. A stale `#[cfg(feature = "cuda")]` is not a compile error: an unknown feature simply evaluates false, so the rename would have silently switched the workflow island runner's device-memory sampling off on every CUDA build while the tree still compiled and every test still passed. Gate on `ort-cuda` instead. That is the feature that actually brings in `onnx-genai-ort/cuda`, where `cuda_rt::device_memory_info` lives, and `native-cuda` enables it transitively -- so the single condition covers both CUDA paths exactly, with no narrowing relative to the old disjunction. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Justin Chuby <justinchuby@users.noreply.github.com>
justinchuby
added a commit
that referenced
this pull request
Aug 21, 2026
Main's #1635 added a lint that resolves every documented `cargo` command against the actual workspace, and it caught two real inconsistencies this branch had left behind. `crates/onnx-genai/src/bin/run_diffusion.rs` was deleted here in "Remove legacy composite pipeline execution", because it drove the strategy/phase composite runtime that `pipeline.workflow` replaces. Ten `scripts/*.py` helpers still shelled out to `target/release/run_diffusion` and told the reader to build it with `cargo build -p onnx-genai --bin run_diffusion`. None of them could run: the binary they exec cannot be built. Delete them with the runner they drive rather than leaving instructions that cannot be followed -- exactly the rot the new lint exists to prevent. Nothing outside the group references them; the only mentions are among themselves and in a dated decisions archive. Also point the workflow performance doc at `native-cuda`, since main's #1629 renamed the feature its example passed to `cargo test`. `scripts/check_documented_commands.py` now exits clean, as do the other quality-gate lints. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Justin Chuby <justinchuby@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.
The word
cudameant two opposite things one crate boundary apart. The CLI'scudaselected ONNX Runtime's CUDA EP; the server'scudaselected ours, andthe CLI's
cudawas wired to the server'sort-cuda. Picking the one thatsounds right gave a binary with none of this repo's kernels in it, which reads
as a 22x regression in whatever you last edited rather than as a wrong build.
That is Trap 7 in the perf skill; it was written down because it cost real
measurement time.
Every crate that offers a choice now names the choice:
ort-cuda ONNX Runtime's CUDAExecutionProvider
native-cuda our
onnx-runtime-ep-cuda, a strict superset of ort-cudaCrates with only one CUDA path (
onnx-genai,onnx-genai-ort,onnx-runtime-session,onnx-runtime-ep-cuda,onnx-runtime-python) keep theplain
cuda, because there is nothing there to confuse it with. That rule, andthe feature matrix, are now written down in
docs/build-features.md.They are deliberately not merged. The CUDA wheels build these same crates with
--features ort-cudaprecisely so no CUDA code is bundled and the wheelbuilders need no CUDA toolkit; one merged
cudawould force every wheel buildto compile our kernels.
native-cudanow also impliesnative-backend, which fixes a real trap ratherthan just renaming one.
onnx-genai-server --features cudaused to compile theentire native CUDA EP and then leave out the native session that dispatches to
it, so the EP was present, unreachable, and the build behaved exactly like the
ORT one while looking like it should not. Same for
onnx-genai-engine,onnx-genai-benchandonnx-genai-capi. capi in particular has zero referencesto
onnx-runtime-ep-cuda, so it was imposing a CUDA toolkit on its build tocompile an EP nothing could call; it now forwards
ort-cuda, which is what itsown comment already said it does.
Verification:
all(cuda, native-backend)pairs, nowredundant and collapsed.
unexpected_cfgsis on by default and reports thelegal values, so a missed rename cannot silently drop code -- confirmed
empirically against a deliberately bogus feature name, and every build below
reports
unexpected_cfg = 0.plus capi ort-cuda.
native-cudagives 129matmul_nbits_gemvsymbols and 52 MB;
ort-cudagives 0 and 39 MB.native-cudaCLI built from this branchand from main agree on symbol counts exactly (gemv 129/129, ep_cuda
3118/3118) and differ by 1952 bytes of embedded feature-name strings.
gains 3 tests over main because
native-cudanow pulls the backend thosetests need, which previously had to be asked for separately.
Call sites updated: wheels.yml, publish.yml, ci.yml, the perf skill's Trap 7,
the H200 and Windows runbooks, the bench and parity READMEs, and the parity
script. Dated benchmark records and
.squadarchives are left alone; theyrecord what was actually run at the time.
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com
Copilot-Session: 0190e2eb-abe4-451f-b36d-44a035a99b7e