Repository navigation
Description
What's your question?
Summary
vortex-cuda/build.rs compiles CUDA kernels to PTX only when nvcc is found on PATH, but it does not register PATH as a rerun trigger. This causes cargo to cache a build.rs result from an environment without nvcc and silently skip PTX compilation when the developer later enters an environment with nvcc (e.g. nix develop). The resulting binary has an empty embedded_ptx table, every load_function_with_suffixes call fails, and execute_cuda falls back to CPU — returning Ok with no kernel launched.
Reproduction
-
From a shell without
nvcconPATH, build any CUDA benchmark:cargo bench -p vortex-cuda --bench alp_cuda --no-run
build.rsruns,is_cuda_available()returnsfalse, PTX compilation is skipped, andembedded_ptx.rsis generated as a no-op (embedded_ptx(_) -> None). Cargo caches this build.rs result. -
Enter a shell with
nvcc(e.g.nix develop) and run the benchmark:nix develop -c bash -c 'cargo bench -p vortex-cuda --bench alp_cuda'Cargo does not re-run
build.rs(none of the declaredrerun-if-changed/rerun-if-env-changedinputs changed), so the stale empty PTX table is linked in. -
Every benchmark reports zero time:
Benchmarking cuda/cuda/alp_f32/0%/100M: Analyzing Criterion.rs ERROR: At least one measurement of benchmark cuda/cuda/alp_f32/0%/100M took zero time per iteration. This should not be possible. If using iter_custom, please verify that your routine is correctly measured.
Root cause
build.rs declares:
println!("cargo:rerun-if-env-changed=PROFILE");but not cargo:rerun-if-env-changed=PATH. The nvcc availability check (is_cuda_available()) depends on PATH, but that dependency is invisible to cargo's build script caching.
The downstream chain:
embedded_ptx.rsreturnsNonefor every module →load_function_with_suffixesfailshybrid_dispatch::try_gpu_dispatchreturnsErrCudaArrayExt::execute_cuda(executor.rs:473-492) catches the error and silently falls back to CPU, returningOk- Benchmarks using
iter_custom+TimedLaunchStrategyreadtimer.load() = 0becauseon_completewas never called (no kernel was launched) - Criterion reports "took zero time per iteration"
Workaround
touch vortex-cuda/build.rsThis forces cargo to re-run build.rs, which will now find nvcc and compile PTX.
Proposed fix
Add cargo:rerun-if-env-changed=PATH to build.rs:
println!("cargo:rerun-if-env-changed=PROFILE");
println!("cargo:rerun-if-env-changed=PATH"); // newThis ensures cargo re-runs build.rs whenever PATH changes, so is_cuda_available() is re-evaluated.
Environment
- OS: NixOS / any system using
nix developfor CUDA tooling - GPU: present, driver loaded (
nvidia-smiworks,/dev/nvidia0exists) nvcc: provided bynix developviacudaPackages.cuda_nvcc, not on the basePATH
Additional note
The silent CPU fallback in execute_cuda (executor.rs:473-492) makes this class of bug very hard to diagnose — a missing PTX looks identical to a successful run from the caller's perspective (returns Ok, no panic). A debug! log is emitted but only visible if a tracing subscriber is initialized, which benchmarks don't do. Consider surfacing this fallback more prominently (e.g. a warning when no PTX is embedded and a GPU is present).
Context
No response
Activity
0ax1 commentedon Jul 10, 2026
Thank you for the detailed report. This is a good remark.