Blackwell 的工具链地雷:sm_120 到底装什么版本
5090 是 sm_120,用错一个 wheel 就是「no kernel image is available」。这一节把环境一次装对,并留下验证命令。
学完这节你能做到
- 用三条命令验证 PyTorch 真的认得这张卡,而不是装完就以为好了
- 装出一套 torch + vLLM + TRL 能互相兼容的环境
- 看到常见报错时,一眼判断是驱动、CUDA、wheel 还是算子的问题
一个报错,能耗掉你一整晚
RuntimeError: CUDA error: no kernel image is available for execution on the device
这是 5090 用户最常见的第一个错误。它的意思不是「显卡坏了」,而是:你装的这个 PyTorch 里,没有为你这张卡编译过的机器码。
搞清楚这一件事,能省掉后面所有玄学:
- 驱动版本(
nvidia-smi右上角那个)—— 内核态驱动,决定这台机器最高能支持哪个 CUDA。 - CUDA Toolkit(
nvcc --version)—— 编译器和头文件。只有你要自己编译算子时才用得上,装 wheel 的人根本不需要它。 - PyTorch 自带的 CUDA runtime(
torch.version.cuda)—— pip wheel 里打包的那份。这个才是决定你能不能跑起来的东西。
新手最常犯的错:看到 nvcc --version 显示 12.4 就以为环境是 12.4,于是去装 cu124 的 torch。实际上 nvcc 完全不参与,要看的是 wheel 自己带的版本。
sm_120 是什么
每一代 NVIDIA 架构有一个 compute capability。GPU 上跑的机器码(SASS)是按 capability 编译的,不通用。
| 架构 | 代表卡 | Compute Capability | gencode |
|---|---|---|---|
| Ampere | A100 | 8.0 | sm_80 |
| Ada | RTX 4090 | 8.9 | sm_89 |
| Hopper | H100 / H200 | 9.0 | sm_90 |
| Blackwell 数据中心 | B200 / GB200 | 10.0 | sm_100 |
| Blackwell 消费级 | RTX 5090 / 5080 | 12.0 | sm_120 |
注意最后两行:B200 和 5090 都叫 Blackwell,但 capability 不一样。一个库写着「支持 Blackwell」并不等于支持 5090。这是 5090 生态混乱的根源。
要让 5090 跑起来,你的 wheel 必须满足两个条件之一:
- 编译时的 arch list 里包含
sm_120(最好的情况,有原生优化的机器码) - 或者至少包含
compute_120/+PTX(退而求其次,运行时 JIT 编译 PTX,第一次调用会卡几秒)
CUDA Toolkit 12.8 是支持 sm_120 的第一个版本。所以:torch.version.cuda 显示 12.6 或更低的 wheel,在 5090 上必定报上面那个错。
装环境
用 uv 管环境,比 conda 快一个数量级,也不会把 CUDA 库装重。
# 1. 确认驱动。要 ≥ 570,Blackwell 建议 580 以上
nvidia-smi
# 2. 建环境
curl -LsSf https://astral.sh/uv/install.sh | sh
uv venv --python 3.12 .venv
source .venv/bin/activate
# 3. 装 PyTorch —— 关键在这一行的 index-url
# cu128 是支持 sm_120 的最低档;更高的 cu129 / cu130 同样可以
uv pip install torch --index-url https://download.pytorch.org/whl/cu128
# 4. 推理引擎与训练库
uv pip install vllm
uv pip install "transformers>=4.51" trl peft datasets accelerate
vLLM 的依赖声明里有 torch,装的时候很可能把你刚装好的 cu128 版本换成 PyPI 上的默认 wheel(那个可能不带 sm_120)。
装完立刻回去跑一遍下面的验证。如果 get_device_capability() 变了或者报错,说明 torch 被换掉了 —— 重装一次 torch,或者用 --no-deps 单独装 vLLM 再手工补齐它的其它依赖。
顺序原则:先装 torch,后装其它;每装一个大包,验证一次。
三条验证命令
装完不要急着跑训练。依次跑这三条,任何一条不过就停下来修。
第一条:PyTorch 认不认得这张卡
python - <<'PY'
import torch
print("torch :", torch.__version__)
print("cuda (wheel):", torch.version.cuda)
print("device :", torch.cuda.get_device_name(0))
print("capability :", torch.cuda.get_device_capability(0))
print("arch list :", torch.cuda.get_arch_list())
PY
要看到的关键两行:
capability : (12, 0)
arch list : [..., 'sm_90', 'sm_100', 'sm_120']
capability 是 (12, 0) 说明卡认出来了;arch list 里有 sm_120 说明 wheel 里有对应的机器码。只有 compute_120 也能跑,但会有首次 JIT 延迟。
第二条:真的算一次
capability 打印正常不代表能算 —— 报错往往在第一次真正调用 kernel 时才出现。
python - <<'PY'
import torch
a = torch.randn(4096, 4096, device="cuda", dtype=torch.bfloat16)
b = torch.randn(4096, 4096, device="cuda", dtype=torch.bfloat16)
c = a @ b
torch.cuda.synchronize()
print("matmul ok:", c.shape, c.dtype)
print("peak mem :", torch.cuda.max_memory_allocated() / 1024**3, "GiB")
PY
这一步过了,PyTorch 侧就算通了。
第三条:vLLM 能生成
python - <<'PY'
from vllm import LLM, SamplingParams
llm = LLM(model="Qwen/Qwen3-0.6B", gpu_memory_utilization=0.5, max_model_len=2048)
out = llm.generate(["1+1=?"], SamplingParams(max_tokens=32, temperature=0))
print(out[0].outputs[0].text)
PY
能打出文字,环境就通了。
- 1.确认驱动版本与显存规格
- 2.确认 PyTorch 编译时包含 sm_120
- 3.真的跑一次 kernel,确认不是「装上了但算不了」
- 4.确认 vLLM 能加载模型并生成
环境验证演练。按上面三条的顺序敲,看到输出后判断它说明了什么。 输入 goals 看目标,hint 要提示。
错误对照表
| 报错 | 真实原因 | 怎么修 |
|---|---|---|
no kernel image is available | wheel 里没有 sm_120 | 换 cu128 及以上的 torch wheel |
PTX was compiled with an unsupported toolchain | 驱动比 wheel 的 CUDA 版本旧 | 升驱动,不要降 torch |
CUDA capability sm_120 is not compatible | 库自己的 arch 白名单没更新 | 升级那个库;或用 TORCH_CUDA_ARCH_LIST="12.0+PTX" 自己编 |
flash_attn 编译失败 | 预编译轮子没有 sm_120 版本 | 别硬编。vLLM 自带的 attention 后端已经够用 |
| 训练几秒后段错误,无 Python traceback | 单卡启用了 DDP | 单卡不要 torchrun,不要 accelerate launch --multi_gpu |
| 显存明显不够但模型很小 | 别的进程占着卡 | nvidia-smi 看进程,杀掉残留的 python |
有人在 5090 上遇到「推理正常,训练几秒后崩溃、没有任何 Python 报错」,排查很久最后发现是 DDP。
单卡场景下 DDP 不但没有任何收益,还会引入 NCCL 通信路径。直接 python train.py 就好 —— 不要 torchrun,不要 accelerate launch --multi_gpu。
WSL2 能跑,但有两个实际代价:整体性能大约是原生的七成;FP8 相关的部分能力受 Windows 显示驱动层限制,行为和原生不一致。
要长时间跑训练,装个原生 Ubuntu。要只是跟着读、偶尔跑小实验,WSL2 够用。
`nvcc --version` 显示 CUDA 12.4,但 `torch.version.cuda` 显示 12.8。在 5090 上能跑吗?
装完 vLLM 后 `no kernel image is available` 又出现了,最可能的原因是什么?
这节课的落点
no kernel image= wheel 里没有 sm_120,不是硬件问题- 三个 CUDA 版本要分清:驱动 / Toolkit / wheel 自带 runtime,起作用的是第三个
- 5090 是 sm_120,与 B200 的 sm_100 不同;「支持 Blackwell」不等于支持 5090
- CUDA 12.8 是支持 sm_120 的起点,torch 要装 cu128 及以上
- 三条验证:capability、真做一次 matmul、vLLM 生成一次
- 单卡不开 DDP;CUDA graph 能捕获就别用
--enforce-eager关掉