fix(kt-kernel): pick default CUDA archs by nvcc version (fixes #2098) - #2103
fix(kt-kernel): pick default CUDA archs by nvcc version (fixes #2098)#2103Anai-Guo wants to merge 3 commits into
Conversation
The build hardcodes CMAKE_CUDA_ARCHITECTURES to 80;86;89;90 whenever CPUINFER_CUDA_ARCHS is unset. nvcc only learns an architecture in a specific toolkit release (sm_89 needs CUDA 11.8+, sm_90 needs CUDA 12.0+), so on an older toolkit nvcc rejects the unknown -gencode targets and the kt-kernel wheel build fails outright (see kvcache-ai#2098, CUDA 11.5). Derive the default arch list from the detected nvcc release instead, keeping only architectures that toolkit supports. An explicitly set CPUINFER_CUDA_ARCHS still wins, and when nvcc cannot be probed we fall back to the previous full list, so modern setups are unchanged.
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
| ) | ||
| return selected | ||
|
|
||
| archs_env = os.environ.get("CPUINFER_CUDA_ARCHS", "").strip() or _default_cuda_archs() |
There was a problem hiding this comment.
The default derivation looks right (checked the sm_80/86/89/90 CUDA-version gates against NVIDIA's own release notes, and they match). One gap in the "explicitly set wins, untouched" claim though.
os.environ.get("CPUINFER_CUDA_ARCHS", "").strip() or _default_cuda_archs() can't tell "unset" from "set to an empty string". Before this PR, CPUINFER_CUDA_ARCHS="" was the documented way to suppress -DCMAKE_CUDA_ARCHITECTURES entirely (the comment above says "if users want to specify CUDA archs, they can set env CPUINFER_CUDA_ARCHS"), since os.environ.get(key, default) only substitutes when the key is absent. With this change, that same explicit empty value now falls through to _default_cuda_archs() and gets a computed arch list instead of no flag at all.
Confirmed with the two snippets isolated from main vs this branch, CPUINFER_CUDA_ARCHS="" in both:
main: cmake_args: []
PR: cmake_args: ['-DCMAKE_CUDA_ARCHITECTURES=80;86;89;90']
Distinguishing "unset" from "empty" ("CPUINFER_CUDA_ARCHS" in os.environ before the .strip()) would keep the explicit opt-out working. Not blocking, this is a narrow edge case, but worth a line since the PR body specifically claims that path is untouched.
|
Good catch — you're right, and the PR body's claim was wrong on that path.
if "CPUINFER_CUDA_ARCHS" in os.environ:
archs_env = os.environ["CPUINFER_CUDA_ARCHS"].strip()
else:
archs_env = _default_cuda_archs()Re-ran your snippet comparison plus a couple more values:
So the only behavior change left is the unset case, which is what #2098 is about. |
| archs = [] | ||
| if ver >= (11, 0): | ||
| archs.append("80") | ||
| if ver >= (11, 1): | ||
| archs.append("86") | ||
| if ver >= (11, 8): | ||
| archs.append("89") | ||
| if ver >= (12, 0): | ||
| archs.append("90") | ||
| selected = ";".join(archs) if archs else full |
There was a problem hiding this comment.
When
ver < (11, 0) all four conditions are false so archs stays empty, and selected falls back to full ("80;86;89;90"). This means a CUDA 10.x toolkit would still get the full arch list, causing the same nvcc rejection the PR aims to fix. In practice CUDA 10.x predates sm_80 itself (A100 launched with CUDA 11.0), so the build would fail for other reasons too, but the fallback could silently produce a misleading error rather than a clear "unsupported toolkit" message. Adding an explicit guard or a warning for ver < (11, 0) would make the failure more actionable.
Prompt To Fix With AI
This is a comment left during a code review.
Path: kt-kernel/setup.py
Line: 703-712
Comment:
When `ver < (11, 0)` all four conditions are false so `archs` stays empty, and `selected` falls back to `full` (`"80;86;89;90"`). This means a CUDA 10.x toolkit would still get the full arch list, causing the same `nvcc` rejection the PR aims to fix. In practice CUDA 10.x predates `sm_80` itself (A100 launched with CUDA 11.0), so the build would fail for other reasons too, but the fallback could silently produce a misleading error rather than a clear "unsupported toolkit" message. Adding an explicit guard or a warning for `ver < (11, 0)` would make the failure more actionable.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
Greptile SummaryThis PR fixes a build failure on older CUDA toolkits (e.g. CUDA 11.5) by replacing the hard-coded
Confidence Score: 4/5The core detection logic is sound, but the sm_90 version gate is wrong: it excludes Hopper kernels on CUDA 11.8/11.x, which is one of the toolkit generations this fix is specifically intended to help. The sm_90 guard uses CUDA 12.0 as the cutoff, but NVIDIA introduced sm_90 support in CUDA 11.8. A user building on CUDA 11.8 with an H100 will get a wheel that silently omits Hopper-optimized code, since archs will contain 80;86;89 rather than 80;86;89;90. Files Needing Attention: kt-kernel/setup.py — the version comparison for sm_90 in _default_cuda_archs
|
| Filename | Overview |
|---|---|
| kt-kernel/setup.py | Adds nvcc version detection to derive safe default CUDA arch list; the sm_90 version gate is wrong (guard uses 12.0, but sm_90 support was added in CUDA 11.8), causing H100 kernels to be silently dropped on CUDA 11.8/11.x toolkits. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[CPUINFER_USE_CUDA=ON] --> B{CPUINFER_CUDA_ARCHS set?}
B -- Yes --> C[Use env value as-is]
B -- No --> D[_default_cuda_archs nvcc_path]
D --> E{nvcc resolvable?}
E -- No --> F[fallback: 80;86;89;90]
E -- Yes --> G[run nvcc --version]
G --> H{parse release X.Y}
H -- parse fails --> F
H -- success --> I{ver >= 11.0?}
I -- No --> F
I -- Yes --> J[archs = 80]
J --> K{ver >= 11.1?}
K -- Yes --> L[add 86]
K -- No --> M[return joined archs]
L --> N{ver >= 11.8?}
N -- Yes --> O[add 89 and 90]
N -- No --> M
O --> M
C --> R{archs_env non-empty AND CMAKE_CUDA_ARCHITECTURES not in args?}
M --> R
F --> R
R -- Yes --> S[append -DCMAKE_CUDA_ARCHITECTURES]
R -- No --> T[skip]
Reviews (2): Last reviewed commit: "refactor(kt-kernel): reuse resolved nvcc..." | Re-trigger Greptile
os.environ.get("CPUINFER_CUDA_ARCHS", "") cannot distinguish "unset" from
"set to an empty string", so CPUINFER_CUDA_ARCHS="" -- the documented way
to suppress -DCMAKE_CUDA_ARCHITECTURES entirely -- fell through to the
derived default instead of leaving the flag off.
Check for key presence before stripping, so an absent variable derives the
nvcc-aware default while an explicitly empty one keeps the previous
no-flag behavior.
The CUDA-arch default helper called find_nvcc_path() a second time even though the same lookup already ran to set -DCMAKE_CUDA_COMPILER, repeating the filesystem probes and risking a mismatch if the two lookups resolved different binaries. Pass the already-resolved path into the helper and only fall back to a fresh lookup when the compiler was user-specified.
|
Thanks @greptile — good catch on Issue 1. Fixed in f827bd3: 🤖 Generated with Claude Code |
|
The fix in f827bd3 looks correct. The flow is clean:
This guarantees both Tip: You can customize Greptile's behavior for this repo with |
|
Friendly ping @maintainers — CI here is gated on the The review feedback has been addressed in f827bd3 and the change is scoped to |
Problem
kt-kernel/setup.pysets-DCMAKE_CUDA_ARCHITECTURES=80;86;89;90wheneverCPUINFER_CUDA_ARCHSis unset:An architecture only becomes valid to
nvccin a specific CUDA toolkit release —sm_89(Ada) needs CUDA 11.8+ andsm_90(Hopper) needs CUDA 12.0+. On an older toolkitnvccrejects the unknown-gencodetargets, so the wheel build fails during compilation with no clear cause. This is exactly what #2098 hits on CUDA 11.5 (a 4×A100 box):Fix
When
CPUINFER_CUDA_ARCHSis not set, derive the default from the detectednvccrelease (reusing the existingfind_nvcc_path()helper) and keep only the architectures that toolkit supports:80;86;89;90(unchanged)80;86;8980;8680Behavior is preserved everywhere it matters:
CPUINFER_CUDA_ARCHSstill wins — untouched.80;86;89;90.nvcccan't be probed, we fall back to the previous full list, so nothing regresses when detection is unavailable.A one-line note is printed when the default is narrowed, pointing users at
CPUINFER_CUDA_ARCHSif they want to override.Fixes #2098.
🤖 Generated with Claude Code