【Bug已解决】[Bug]: NVCC compilation error when launching DeepSeek-V4-Flash on H100 解决方案一、现象长什么样在 H100Hoppersm_90上编译/启动 DeepSeek-V4-Flash带自定义 CUDA Flash 内核的变体时nvcc编译报错nvcc fatal : Unsupported gpu architecture compute_100或error: #error -- unsupported architectural feature: this kernel requires sm_100 (Blackwell)或ptxas error : OpCode not supported on .target sm_90几个典型表征只在 H100sm_90上编译 DeepSeek-V4-Flash 出现在 B200sm_100正常说明自定义内核用了 Blackwellsm_100专属指令/特性H100 的 sm_90 不支持nvcc 编译/ptxas 阶段直接拒。报错在nvcc/ptxas阶段不是 Python 运行期而是 CUDA 代码编译期。内核里用了sm_100才有的指令如某些 Hopper→Blackwell 新增的 MMA / 控制流目标架构设成 sm_90 时 ptxas 报错。-gencode/TORCH_CUDA_ARCH_LIST设错编译时生成代码的架构列表若含compute_100而本机 nvcc/驱动只到 sm_90直接Unsupported gpu architecture。这不是权重坏而是DeepSeek-V4-Flash 的自定义内核针对 Blackwell(sm_100) 优化编译目标架构被设成了 H100 不支持的 sm_100导致 nvcc 编译失败。下面给出定位与修复架构探测 编译目标对齐。二、背景CUDA 内核编译靠nvcc的-gencode archcompute_X,codesm_X或 PyTorch 的TORCH_CUDA_ARCH_LIST。它干两件事compute_X生成 PTX虚拟码X 决定 PTX 版本sm_X把 PTX 编译成具体 GPU 的 cubinX 决定目标硬件特性。DeepSeek-V4-Flash 的 Flash 内核为了极致性能可能用了sm_100 专属特性Blackwell 的新指令。如果编译时把TORCH_CUDA_ARCH_LIST设成10.0想给 Blackwell 编但在 H100sm_90机器上 nvcc 连compute_100都接受不了nvcc 版本 支持 sm_100 的版本→Unsupported gpu architecture或内核源码里#if __CUDA_ARCH__ 100用了 sm_100 指令但编译目标 sm_90 触发了#error守卫就会 nvcc 编译失败。根因是编译目标架构sm_100与 H100 硬件sm_90不匹配且内核没为 sm_90 提供回退路径。修复就是探测本机 GPU 架构把编译目标设到 sm_90 并提供 sm_90 兼容的 kernel 路径。下面用可运行代码实现架构探测 编译目标生成。三、根因拆成两条根因编译目标架构设成 sm_100H100(sm_90) 不支持TORCH_CUDA_ARCH_LIST10.0或-gencode archcompute_100但 H100 是 sm_90nvcc/ptxas 拒绝。根因是编译目标架构 本机硬件架构。内核无 sm_90 回退路径Flash 内核只对 sm_100 实现了优化路径没为 sm_90 提供等价实现或#error守卫直接拒 sm_90导致 H100 完全编不过。根因是内核缺架构回退。修复方向编译前探测本机 GPU 架构sm_90把编译目标设到 sm_90内核提供按架构分派——sm_90 走兼容路径、sm_100 走优化路径并校验 nvcc 版本是否支持目标架构。四、最小可运行复现下面复现编译目标架构超过本机硬件的判定逻辑def nvcc_gencode(target_sm, nvcc_max_sm, gpu_sm): 模拟 nvcc -gencode 的架构检查。 if target_sm nvcc_max_sm: raise RuntimeError(fnvcc 不支持架构 sm_{target_sm}最高 sm_{nvcc_max_sm}) if target_sm gpu_sm: raise RuntimeError( f编译目标 sm_{target_sm} 超过本机 GPU sm_{gpu_sm}无法运行) return farchcompute_{target_sm},codesm_{target_sm} # 复现H100 (gpu_sm90) 上目标设 100nvcc 只到 100 但 GPU 是 90 try: nvcc_gencode(100, nvcc_max_sm100, gpu_sm90) except RuntimeError as e: print(复现:, e) # 编译目标 sm_100 超过本机 GPU sm_90复现: ...超过本机 GPU sm_90即复现。下面把目标降到 sm_90 并提供回退。五、解决方案第一层最小直接修复最小修复编译前探测本机 GPU 架构把编译目标设到本机支持的最高 smH100→90并提供按架构分派的 kernel 路径。def pick_compile_arch(gpu_sm: int, nvcc_max_sm: int) - int: 选本机能跑的最高编译目标不超过 GPU 也不超过 nvcc。 target min(gpu_sm, nvcc_max_sm) if target gpu_sm: target gpu_sm return target def gencode_flags(target_sm: int) - str: 生成 nvcc -gencode 参数。 return f-gencode archcompute_{target_sm},codesm_{target_sm} # 模拟按架构分派的 kernel 源码骨架 KERNEL_DISPATCH #if __CUDA_ARCH__ 100 // Blackwell sm_100 优化路径新指令 flash_kernel_sm100(...); #elif __CUDA_ARCH__ 900 // Hopper sm_90 兼容路径等价实现不用 sm_100 专属指令 flash_kernel_sm90(...); #else #error 需要 sm_90 及以上 #endif # 复现修复H100 → 目标 90 target pick_compile_arch(gpu_sm90, nvcc_max_sm100) print(H100 编译目标:, gencode_flags(target)) # archcompute_90,codesm_90这一层改动让 H100 上编译目标正确设为 sm_90内核走 sm_90 兼容路径nvcc 不再因compute_100拒绝。六、解决方案第二层结构化改进把架构探测 编译目标生成 内核分派做成结构化组件支持多 GPU 取最小架构、校验 nvcc 能力、输出完整 gencode 列表。from dataclasses import dataclass from typing import List dataclass class BuildTarget: gpu_arches: List[int] # 本机各卡架构如 [90, 90] nvcc_max_sm: int # nvcc 支持的最高 sm def compute_gencode(target: BuildTarget) - List[str]: 为所有卡生成 gencode取最小架构保证都能跑。 # 多卡按最严格的最小架构编译确保所有卡都能运行 min_arch min(target.gpu_arches) compile_sm min(min_arch, target.nvcc_max_sm) if compile_sm min_arch: compile_sm min_arch flags [ f-gencode archcompute_{compile_sm},codesm_{compile_sm}, # 同时保留 PTXcompute_X以便老驱动 JIT f-gencode archcompute_{compile_sm},codecompute_{compile_sm}, ] return flags def check_nvcc_support(nvcc_max_sm: int, want_sm: int): if want_sm nvcc_max_sm: raise RuntimeError( fnvcc 最高支持 sm_{nvcc_max_sm}无法编译目标 sm_{want_sm}。 f请升级 nvccCUDA toolkit或降级编译目标。) # 用法H100 单卡 bt BuildTarget(gpu_arches[90], nvcc_max_sm100) check_nvcc_support(bt.nvcc_max_sm, 90) print(gencode:, compute_gencode(bt)) # sm_90compute_gencode多卡取最小架构、并保留 PTX 供老驱动 JITcheck_nvcc_support在编译前校验 nvcc 能力双保险。七、解决方案第三层断言 / CI 守护nvcc 编译错误最怕本地能编、H100 不能。用断言守两条不变量def check_build_target_invariants(bt: BuildTarget, want_sm: int): # 不变量 1编译目标不得超过本机 GPU 架构 compile_sm min(min(bt.gpu_arches), bt.nvcc_max_sm) assert compile_sm min(bt.gpu_arches), 编译目标超过 GPU 架构 # 不变量 2编译目标不得超过 nvcc 能力 assert compile_sm bt.nvcc_max_sm, 编译目标超过 nvcc 支持 # 不变量 3gencode 必须包含匹配本机 GPU 的 sm flags compute_gencode(bt) assert any(fsm_{min(bt.gpu_arches)} in f for f in flags) return True def test_h100_build_target(): # H100: gpu90, nvcc 到 100 bt BuildTarget([90], 100) check_build_target_invariants(bt, want_sm90) # 若误设目标 100 应被拦 try: check_nvcc_support(bt.nvcc_max_sm, 100) # 100100 通过但 GPU 是 90 except RuntimeError: pass # 真正校验编译目标最终必须是 90min gpu assert min(bt.gpu_arches) 90 print(OK: H100 编译目标不变量通过) if __name__ __main__: test_h100_build_target()把test_h100_build_target接进 CI含 H100 runner 或仅做配置校验锁死编译目标不超过本机架构。八、排查清单DeepSeek-V4-Flash 在 H100 上 nvcc 编译错误按序查看错误是Unsupported gpu architecture还是ptxas ... not supported前者是 gencode 架构设错如 compute_100后者是内核用了 sm_100 专属指令且目标 sm_90。探测本机 GPU 架构nvidia-smi --query-gpucompute_cap看 H100 是 sm_90。编译目标必须 ≤ 90。设对TORCH_CUDA_ARCH_LISTH100 上用9.0别用10.0那是 Blackwell。nvcc -gencode archcompute_90,codesm_90。内核提供 sm_90 回退Flash 内核用#if __CUDA_ARCH__ 900提供 sm_90 兼容路径避免#error直接拒 H100。sm_100 优化路径只在 sm_100 机器上编。校验 nvcc 版本nvcc 要支持目标架构的 PTX 版本。H100(sm_90) 需 CUDA 11.8 的 nvcc若 nvcc 太旧连 compute_90 都嫌新升级 CUDA toolkit。多卡取最小架构多 H100 时按最小架构编译保证都能跑混合机型H100B200按最严格H100, sm_90编译B200 上以 sm_90 路径运行牺牲一点优化但能跑。CI 接test_h100_build_target校验编译目标 ≤ 本机架构且 ≤ nvcc 能力防止误设 sm_100。九、小结DeepSeek-V4-Flash 在 H100 上 nvcc 编译错误的根因是自定义 Flash 内核针对 Blackwell(sm_100) 优化编译目标架构被设成 H100(sm_90) 不支持的 sm_100且内核缺 sm_90 回退路径。三层修复第一层pick_compile_arch探测本机 GPU 架构把编译目标设到 sm_90H100内核用#if __CUDA_ARCH__分派 sm_90 兼容路径第二层compute_gencode多卡取最小架构 保留 PTX 供 JITcheck_nvcc_support编译前校验 nvcc 能力双保险第三层CI 断言守住编译目标 ≤ GPU 架构 / ≤ nvcc 能力 / gencode 含本机 sm任何误设 sm_100 立即红。落实后DeepSeek-V4-Flash 在 H100 上编译目标正确设为 sm_90、走兼容 kernel 路径nvcc 不再因compute_100或 sm_100 指令拒绝B200 上仍可走 sm_100 优化路径。
【Bug已解决】[Bug]: NVCC compilation error when launching DeepSeek-V4-Flash on H100 解决方案
【Bug已解决】[Bug]: NVCC compilation error when launching DeepSeek-V4-Flash on H100 解决方案一、现象长什么样在 H100Hoppersm_90上编译/启动 DeepSeek-V4-Flash带自定义 CUDA Flash 内核的变体时nvcc编译报错nvcc fatal : Unsupported gpu architecture compute_100或error: #error -- unsupported architectural feature: this kernel requires sm_100 (Blackwell)或ptxas error : OpCode not supported on .target sm_90几个典型表征只在 H100sm_90上编译 DeepSeek-V4-Flash 出现在 B200sm_100正常说明自定义内核用了 Blackwellsm_100专属指令/特性H100 的 sm_90 不支持nvcc 编译/ptxas 阶段直接拒。报错在nvcc/ptxas阶段不是 Python 运行期而是 CUDA 代码编译期。内核里用了sm_100才有的指令如某些 Hopper→Blackwell 新增的 MMA / 控制流目标架构设成 sm_90 时 ptxas 报错。-gencode/TORCH_CUDA_ARCH_LIST设错编译时生成代码的架构列表若含compute_100而本机 nvcc/驱动只到 sm_90直接Unsupported gpu architecture。这不是权重坏而是DeepSeek-V4-Flash 的自定义内核针对 Blackwell(sm_100) 优化编译目标架构被设成了 H100 不支持的 sm_100导致 nvcc 编译失败。下面给出定位与修复架构探测 编译目标对齐。二、背景CUDA 内核编译靠nvcc的-gencode archcompute_X,codesm_X或 PyTorch 的TORCH_CUDA_ARCH_LIST。它干两件事compute_X生成 PTX虚拟码X 决定 PTX 版本sm_X把 PTX 编译成具体 GPU 的 cubinX 决定目标硬件特性。DeepSeek-V4-Flash 的 Flash 内核为了极致性能可能用了sm_100 专属特性Blackwell 的新指令。如果编译时把TORCH_CUDA_ARCH_LIST设成10.0想给 Blackwell 编但在 H100sm_90机器上 nvcc 连compute_100都接受不了nvcc 版本 支持 sm_100 的版本→Unsupported gpu architecture或内核源码里#if __CUDA_ARCH__ 100用了 sm_100 指令但编译目标 sm_90 触发了#error守卫就会 nvcc 编译失败。根因是编译目标架构sm_100与 H100 硬件sm_90不匹配且内核没为 sm_90 提供回退路径。修复就是探测本机 GPU 架构把编译目标设到 sm_90 并提供 sm_90 兼容的 kernel 路径。下面用可运行代码实现架构探测 编译目标生成。三、根因拆成两条根因编译目标架构设成 sm_100H100(sm_90) 不支持TORCH_CUDA_ARCH_LIST10.0或-gencode archcompute_100但 H100 是 sm_90nvcc/ptxas 拒绝。根因是编译目标架构 本机硬件架构。内核无 sm_90 回退路径Flash 内核只对 sm_100 实现了优化路径没为 sm_90 提供等价实现或#error守卫直接拒 sm_90导致 H100 完全编不过。根因是内核缺架构回退。修复方向编译前探测本机 GPU 架构sm_90把编译目标设到 sm_90内核提供按架构分派——sm_90 走兼容路径、sm_100 走优化路径并校验 nvcc 版本是否支持目标架构。四、最小可运行复现下面复现编译目标架构超过本机硬件的判定逻辑def nvcc_gencode(target_sm, nvcc_max_sm, gpu_sm): 模拟 nvcc -gencode 的架构检查。 if target_sm nvcc_max_sm: raise RuntimeError(fnvcc 不支持架构 sm_{target_sm}最高 sm_{nvcc_max_sm}) if target_sm gpu_sm: raise RuntimeError( f编译目标 sm_{target_sm} 超过本机 GPU sm_{gpu_sm}无法运行) return farchcompute_{target_sm},codesm_{target_sm} # 复现H100 (gpu_sm90) 上目标设 100nvcc 只到 100 但 GPU 是 90 try: nvcc_gencode(100, nvcc_max_sm100, gpu_sm90) except RuntimeError as e: print(复现:, e) # 编译目标 sm_100 超过本机 GPU sm_90复现: ...超过本机 GPU sm_90即复现。下面把目标降到 sm_90 并提供回退。五、解决方案第一层最小直接修复最小修复编译前探测本机 GPU 架构把编译目标设到本机支持的最高 smH100→90并提供按架构分派的 kernel 路径。def pick_compile_arch(gpu_sm: int, nvcc_max_sm: int) - int: 选本机能跑的最高编译目标不超过 GPU 也不超过 nvcc。 target min(gpu_sm, nvcc_max_sm) if target gpu_sm: target gpu_sm return target def gencode_flags(target_sm: int) - str: 生成 nvcc -gencode 参数。 return f-gencode archcompute_{target_sm},codesm_{target_sm} # 模拟按架构分派的 kernel 源码骨架 KERNEL_DISPATCH #if __CUDA_ARCH__ 100 // Blackwell sm_100 优化路径新指令 flash_kernel_sm100(...); #elif __CUDA_ARCH__ 900 // Hopper sm_90 兼容路径等价实现不用 sm_100 专属指令 flash_kernel_sm90(...); #else #error 需要 sm_90 及以上 #endif # 复现修复H100 → 目标 90 target pick_compile_arch(gpu_sm90, nvcc_max_sm100) print(H100 编译目标:, gencode_flags(target)) # archcompute_90,codesm_90这一层改动让 H100 上编译目标正确设为 sm_90内核走 sm_90 兼容路径nvcc 不再因compute_100拒绝。六、解决方案第二层结构化改进把架构探测 编译目标生成 内核分派做成结构化组件支持多 GPU 取最小架构、校验 nvcc 能力、输出完整 gencode 列表。from dataclasses import dataclass from typing import List dataclass class BuildTarget: gpu_arches: List[int] # 本机各卡架构如 [90, 90] nvcc_max_sm: int # nvcc 支持的最高 sm def compute_gencode(target: BuildTarget) - List[str]: 为所有卡生成 gencode取最小架构保证都能跑。 # 多卡按最严格的最小架构编译确保所有卡都能运行 min_arch min(target.gpu_arches) compile_sm min(min_arch, target.nvcc_max_sm) if compile_sm min_arch: compile_sm min_arch flags [ f-gencode archcompute_{compile_sm},codesm_{compile_sm}, # 同时保留 PTXcompute_X以便老驱动 JIT f-gencode archcompute_{compile_sm},codecompute_{compile_sm}, ] return flags def check_nvcc_support(nvcc_max_sm: int, want_sm: int): if want_sm nvcc_max_sm: raise RuntimeError( fnvcc 最高支持 sm_{nvcc_max_sm}无法编译目标 sm_{want_sm}。 f请升级 nvccCUDA toolkit或降级编译目标。) # 用法H100 单卡 bt BuildTarget(gpu_arches[90], nvcc_max_sm100) check_nvcc_support(bt.nvcc_max_sm, 90) print(gencode:, compute_gencode(bt)) # sm_90compute_gencode多卡取最小架构、并保留 PTX 供老驱动 JITcheck_nvcc_support在编译前校验 nvcc 能力双保险。七、解决方案第三层断言 / CI 守护nvcc 编译错误最怕本地能编、H100 不能。用断言守两条不变量def check_build_target_invariants(bt: BuildTarget, want_sm: int): # 不变量 1编译目标不得超过本机 GPU 架构 compile_sm min(min(bt.gpu_arches), bt.nvcc_max_sm) assert compile_sm min(bt.gpu_arches), 编译目标超过 GPU 架构 # 不变量 2编译目标不得超过 nvcc 能力 assert compile_sm bt.nvcc_max_sm, 编译目标超过 nvcc 支持 # 不变量 3gencode 必须包含匹配本机 GPU 的 sm flags compute_gencode(bt) assert any(fsm_{min(bt.gpu_arches)} in f for f in flags) return True def test_h100_build_target(): # H100: gpu90, nvcc 到 100 bt BuildTarget([90], 100) check_build_target_invariants(bt, want_sm90) # 若误设目标 100 应被拦 try: check_nvcc_support(bt.nvcc_max_sm, 100) # 100100 通过但 GPU 是 90 except RuntimeError: pass # 真正校验编译目标最终必须是 90min gpu assert min(bt.gpu_arches) 90 print(OK: H100 编译目标不变量通过) if __name__ __main__: test_h100_build_target()把test_h100_build_target接进 CI含 H100 runner 或仅做配置校验锁死编译目标不超过本机架构。八、排查清单DeepSeek-V4-Flash 在 H100 上 nvcc 编译错误按序查看错误是Unsupported gpu architecture还是ptxas ... not supported前者是 gencode 架构设错如 compute_100后者是内核用了 sm_100 专属指令且目标 sm_90。探测本机 GPU 架构nvidia-smi --query-gpucompute_cap看 H100 是 sm_90。编译目标必须 ≤ 90。设对TORCH_CUDA_ARCH_LISTH100 上用9.0别用10.0那是 Blackwell。nvcc -gencode archcompute_90,codesm_90。内核提供 sm_90 回退Flash 内核用#if __CUDA_ARCH__ 900提供 sm_90 兼容路径避免#error直接拒 H100。sm_100 优化路径只在 sm_100 机器上编。校验 nvcc 版本nvcc 要支持目标架构的 PTX 版本。H100(sm_90) 需 CUDA 11.8 的 nvcc若 nvcc 太旧连 compute_90 都嫌新升级 CUDA toolkit。多卡取最小架构多 H100 时按最小架构编译保证都能跑混合机型H100B200按最严格H100, sm_90编译B200 上以 sm_90 路径运行牺牲一点优化但能跑。CI 接test_h100_build_target校验编译目标 ≤ 本机架构且 ≤ nvcc 能力防止误设 sm_100。九、小结DeepSeek-V4-Flash 在 H100 上 nvcc 编译错误的根因是自定义 Flash 内核针对 Blackwell(sm_100) 优化编译目标架构被设成 H100(sm_90) 不支持的 sm_100且内核缺 sm_90 回退路径。三层修复第一层pick_compile_arch探测本机 GPU 架构把编译目标设到 sm_90H100内核用#if __CUDA_ARCH__分派 sm_90 兼容路径第二层compute_gencode多卡取最小架构 保留 PTX 供 JITcheck_nvcc_support编译前校验 nvcc 能力双保险第三层CI 断言守住编译目标 ≤ GPU 架构 / ≤ nvcc 能力 / gencode 含本机 sm任何误设 sm_100 立即红。落实后DeepSeek-V4-Flash 在 H100 上编译目标正确设为 sm_90、走兼容 kernel 路径nvcc 不再因compute_100或 sm_100 指令拒绝B200 上仍可走 sm_100 优化路径。