【Bug已解决】[Build] Windows Release builds only support a selected number of CUDA compute capabilities 解决方案一、现象长什么样用官方Windows Release 构建的 ONNX RuntimeCUDA EP跑模型在某些 GPU 架构上CUDA EP 要么起不来要么回退到 CPU并提示找不到对应计算能力的 kernelORT CUDA: no kernel image available for device with compute capability 9.0 # 或 nvrtc: GPU arch 90 not supported by this build # 或 CUDA EP 静默不可用只有 CPU 在跑具体表现在同一份 ORT Windows Release 包下老显卡如 sm_50/60或新显卡如 sm_90 Ada/Hopper用不了 CUDA EP而中间档如 sm_70/75/80正常。只在Windows Release构建出现自己从源码用完整CUDA_ARCHITECTURES编出来的 Debug/自定义构建却能在那张卡上跑。说明不是 GPU 坏了而是这个 Release 包编译 CUDA 内核时只覆盖了一部分 compute capabilitySM。关键特征Release 构建为了缩短编译时间/减小体积硬编码了一个较小的 CUDA 架构子集于是“不在名单里”的 GPU 架构没有对应的 kernel 镜像CUDA EP 对新/老卡失效。二、背景NVIDIA GPU 用compute capability计算能力简称 SM 版本如 7.0、8.0、8.9、9.0区分架构。CUDA 内核要在某张卡上跑编译时必须针对该架构生成内核镜像kernel image / cubin——也就是nvcc -gencode archcompute_XX,codesm_XX。一个 CUDA 程序可以内嵌多个架构的 kernel 镜像fatbinary运行时按当前 GPU 选匹配的。但每多编一个架构编译时间、二进制体积都显著增加。于是 ORT 的Windows Release 构建脚本为了控制成本只给了一个精选的架构子集比如只编 sm_70/75/80期望覆盖“大多数用户”。问题在于新架构发布快用户买了 sm_90Hopper/Ada的卡但 Release 包还停在 sm_80 → 没有对应镜像CUDA EP 起不来。老架构仍有存量一些嵌入式/老数据中心卡是 sm_50/60Release 包若没编也用不了。硬编码不可配构建脚本把架构列表写死用户想在 Release 里多编一个架构只能自己从源码重编门槛高。这就造成“同一份 Release 包有的 GPU 能用 CUDA、有的不能”的割裂体验。三、根因根因是Windows Release 构建把CUDA_ARCHITECTURES硬编码成一个较小的子集且没有给用户提供“按需增编架构”的机制导致名单外的 GPU 没有 kernel 镜像架构列表写死CMake/构建脚本里CUDA_ARCHITECTURES是固定几个如70;75;80不包含新/老架构用户无法在 Release 包层面扩展。缺 forward-compat虚拟架构没利用compute_XX虚拟架构 JIT即时编译或CUDA_CACHED_IR使新 GPU 能向后兼容运行在支持的虚拟架构范围内 JIT 出对应镜像。构建成本与覆盖度的失衡Release 只编子集是为省时省力但代价是可见的兼容性断裂且错误提示不清用户不知道是“架构没编”。文档缺失用户不知道这个 Release 包支持哪些 SM遇到“no kernel image”只能猜。一句话Release 构建的 CUDA 架构覆盖是写死的子集新/老 GPU 没被编进 kernel 镜像且没提供 forward-compat 或自定义增编途径于是 CUDA EP 在名单外架构上失效。四、最小可运行复现下面用 Python 模拟“构建期选架构子集、运行期按 GPU 选镜像”的机理复现“名单外架构无镜像”from dataclasses import dataclass from typing import Set dataclass class BuildConfig: # Release 构建硬编码的架构子集 built_arches: Set[str] {70, 75, 80} def load_cuda_ep_buggy(cfg: BuildConfig, device_arch: str) - str: 错误只认构建期编进去的架构子集。 if device_arch in cfg.built_arches: return CUDA raise RuntimeError(fno kernel image for compute capability {device_arch}) def load_cuda_ep_fixed(cfg: BuildConfig, device_arch: str, forward_compat: Set[str]) - str: 修复在子集内直接用子集外用 forward-compat 虚拟架构 JIT。 if device_arch in cfg.built_arches: return CUDA if device_arch in forward_compat: return CUDA(jit) # 虚拟架构 JIT 出镜像 raise RuntimeError(farch {device_arch} not supported even via JIT) cfg BuildConfig() print(load_cuda_ep_buggy(cfg, 90)) # 崩Release 没编 sm_90 print(load_cuda_ep_fixed(cfg, 90, forward_compat{90})) # CUDA(jit)buggy在sm_90直接崩fixed通过 forward-compat 虚拟架构 JIT 支持新卡——正是 Release 包该补的能力。五、解决方案第一层最小直接修复最小修复是让 Windows Release 构建的CUDA_ARCHITECTURES可配置默认含主流最新并启用 forward-compat 虚拟架构使名单外但兼容的 GPU 能 JIT 运行# CMakeLists.txt修复片段 # 默认覆盖主流 最新允许用户通过 -DORT_CUDA_ARCHS... 增编 set(ORT_CUDA_ARCHS 70;75;80;90 CACHE STRING CUDA compute capabilities to build) # 启用虚拟架构 forward-compat用 compute_XX 生成可被 JIT 的 IR set(CMAKE_CUDA_ARCHITECTURES ${ORT_CUDA_ARCHS}) # 关键包含虚拟架构如 compute_90以支持未来卡的 JIT foreach(arch ${ORT_CUDA_ARCHS}) list(APPEND CUDA_GENCODES -gencode archcompute_${arch},codesm_${arch}) list(APPEND CUDA_GENCODES -gencode archcompute_${arch},codecompute_${arch}) # 虚拟架构 endforeach()配套在 CUDA EP 初始化时若设备架构不在内置镜像里尝试 JIT基于虚拟架构的缓存 IR失败再回退 CPU 并明确告知原因。这一层让 Release 包既覆盖最新架构又能 forward-compat 支持未来卡CUDA EP 在更多 GPU 上可用。六、解决方案第二层结构性改进把“Release 构建支持哪些 CUDA 架构、是否 forward-compat、如何告知用户”收口成唯一的配置对象OrtWindowsCudaArchPolicy构建与运行时读它from dataclasses import dataclass from typing import Tuple dataclass(frozenTrue) class OrtWindowsCudaArchPolicy: Windows Release CUDA 架构支持的单一事实来源。 # 默认编译的架构子集含最新 built_arches: Tuple[str, ...] (70, 75, 80, 90) # 启用虚拟架构 forward-compatJIT 支持未来卡 forward_compat_virtual_arch: bool True # 用户可通过构建参数增编架构不写死 user_extensible: bool True # 不支持时明确报错含架构与支持列表不静默回退 surface_unsupported_arch: bool True # 代码评审卡点 forbidden_patterns: Tuple[str, ...] ( CUDA_ARCHITECTURES hardcoded to 70;75;80, silent CPU fallback on unknown arch, ) def resolve(self, device_arch: str, jit_available: bool) - str: if device_arch in self.built_arches: return CUDA if self.forward_compat_virtual_arch and jit_available: return CUDA(jit) raise RuntimeError( fcompute capability {device_arch} not in {self.built_arches}; frebuild with -DORT_CUDA_ARCHS... or use JIT-capable build) def describe(self) - str: return Release 编主流最新架构、forward-compat JIT、不支持明确报错 POLICY OrtWindowsCudaArchPolicy() def plan_cuda_arch(device_arch: str, jit_available: bool True, policy: OrtWindowsCudaArchPolicy POLICY) - str: return policy.resolve(device_arch, jit_available)构建脚本与 CUDA EP 都读POLICY架构覆盖与 forward-compat 被固化用户不再被写死的子集挡在门外。七、解决方案第三层断言 / CI 守护把“架构可配、forward-compat、不支持明确报错”做成断言。下面用 pytest 守护import pytest def test_built_arches_include_latest(policy): assert 90 in policy.built_arches # 含最新架构 assert 70 in policy.built_arches # 含老架构 def test_forward_compat(policy): assert policy.forward_compat_virtual_arch is True assert policy.resolve(90, jit_availableTrue) CUDA(jit) def test_user_extensible(policy): assert policy.user_extensible is True assert CUDA_ARCHITECTURES hardcoded in policy.forbidden_patterns def test_surface_unsupported(policy): assert policy.surface_unsupported_arch is True with pytest.raises(RuntimeError): policy.resolve(35, jit_availableFalse) # 老到不支持 def test_no_silent_fallback(policy): assert silent CPU fallback on unknown arch in policy.forbidden_patterns这五组断言锁住(1) 含最新老架构(2) forward-compat(3) 用户可增编(4) 不支持明确报错(5) 禁止静默回退。CI 跑通即代表 Release 包的 CUDA 架构覆盖不会被写死子集限制。八、排查清单遇到 Windows Release CUDA EP 在新/老 GPU 上不可用看报错是不是架构相关no kernel image for compute capability XX→ 名单外架构本题。查 Release 编了哪些架构CUDA_ARCHITECTURES是不是写死的小子集。查 forward-compat有没有虚拟架构 JIT让未来卡也能跑。改可配置 虚拟架构默认含主流最新允许用户-DORT_CUDA_ARCHS增编开 forward-compat。统一到OrtWindowsCudaArchPolicyCI 断言禁止写死子集。明确报错不支持时给出架构与支持列表不静默回退 CPU。端到端在 sm_90 等新卡上 CUDA EP 可用或 JIT 可用。九、小结[Build] Windows Release builds only support a selected number of CUDA compute capabilities的根因是ONNX Runtime 的 Windows Release 构建把CUDA_ARCHITECTURES硬编码成一个较小的架构子集如只编 sm_70/75/80以缩短编译、减小体积但导致名单外的 GPU新架构如 sm_90、或老架构没有对应的 kernel 镜像CUDA EP 在这些卡上无法启动/回退且缺少 forward-compat 虚拟架构 JIT 与明确的报错用户难以诊断。最小修复是让CUDA_ARCHITECTURES可配置默认含主流最新并启用虚拟架构 forward-compat 使未来卡可 JIT结构性改进是用唯一的OrtWindowsCudaArchPolicy固化架构覆盖与降级语义CI 用五组断言守护“含最新架构、forward-compat、禁止静默回退”。记住CUDA 发布包若把架构写死GPU 一更新用户就掉队虚拟架构 可配置编译才是长久之计。