PyTorch安装后发现CUDA不可用怎么切换GPU版本

文章导读
装完 PyTorch 后 torch.cuda.is_available() 返回 False,通常不是系统里“没装 CUDA”,而是两种情况之一:pip 或 conda 给当前环境装成了 CPU 版构建包;或者装到的 GPU 版构建包依赖的 CUDA runtime 高于显卡驱动能支持的上限。切换 GPU 版本的正确动作不是重装系统 CUDA Toolkit,而是在当前 Python 环境里换成
📋 目录
  1. A 先确认当前场景和目标
  2. B 按这个顺序处理
  3. C 改完后怎么验证
  4. D 容易忽略的边界
A A

装完 PyTorch 后 torch.cuda.is_available() 返回 False,通常不是系统里“没装 CUDA”,而是两种情况之一:pip 或 conda 给当前环境装成了 CPU 版构建包;或者装到的 GPU 版构建包依赖的 CUDA runtime 高于显卡驱动能支持的上限。切换 GPU 版本的正确动作不是重装系统 CUDA Toolkit,而是在当前 Python 环境里换成与驱动匹配的 PyTorch 构建包,再用一段最小代码确认 torch 真正拿到了设备。

先判断是“装错包”还是“驱动太旧”:用 torch.version.cuda 看当前包自带的 CUDA runtime,用 nvidia-smi 右上角看驱动支持的最高 CUDA 版本。前者为 None 说明装的是 CPU 版,需要按 GPU 索引重装;前者高于后者,需要换更低 CUDA 标签的包或升级驱动。切换只在目标虚拟环境内做,不要动系统级 CUDA 目录;验证标准是 is_available() 为 True 且能在 nvidia-smi 里看到对应进程。

先确认当前场景和目标

问题成立的前提是机器上确实有可用的 NVIDIA 显卡和驱动,且读者在某个明确的 Python 环境(虚拟环境、conda 环境或容器)里操作。如果 nvidia-smi 本身报“command not found”或提示驱动未加载,那么先解决驱动问题,切换 PyTorch 版本不会有任何效果。反过来,如果 nvidia-smi 正常输出显卡型号和显存,问题基本就落在 Python 侧的构建包上。

动手前先记录四项信息,后面选择版本全靠这四项:显卡驱动版本、驱动支持的 CUDA 版本上限、当前 torch 的版本字符串、当前 torch 自带的 CUDA runtime。第三方包索引里同一条 pip install torch 在不同源上可能给出不同结果,因此还要确认自己用的索引地址是谁提供的。

# 1) 驱动与显卡
nvidia-smi

# 2) 当前环境里的 torch 究竟是什么
python -c "import torch; print('torch:', torch.__version__); print('built cuda:', torch.version.cuda); print('available:', torch.cuda.is_available()); print('count:', torch.cuda.device_count())"

# 3) 确认 pip / python 来自哪个环境
which python
python -m pip -V

判断条件很直接:built cuda 打印 None,说明当前是 CPU 版构建包,切换方式是重装 GPU 版;built cuda 有值但 available 为 False,多半是驱动版本低于该 runtime 要求,或运行在没挂载 GPU 的容器里。

按这个顺序处理

顺序建议从“隔离环境”开始,避免把系统里的旧包和新包混在一起。先在目标环境内卸载现有的 torch 三件套,再按 GPU 索引装回同一组版本,torch、torchvision、torchaudio 三者要一起换,只换 torch 容易在 import 时报符号缺失。

  1. 进入出问题的那个环境,确认 which python 指向目标环境的解释器。
  2. 用 python -m pip uninstall -y torch torchvision torchaudio 清掉旧包;conda 环境里也用 pip 卸载,避免 pip 与 conda 各留一份。
  3. 按驱动支持的 CUDA 版本选择标签,用 PyTorch 官方索引重装。下例中的 ${CUDA_TAG} 需要替换成形如 cu118、cu121 的具体标签,实际可用标签以 PyTorch 官网安装选择器当前给出的为准,不要凭记忆写死。
  4. 重新打开一个解释器进程验证,不要在已经 import 过 torch 的交互式会话里验证,旧模块不会自动刷新。
# 通用骨架:把 CUDA_TAG 换成与驱动匹配的标签
python -m pip uninstall -y torch torchvision torchaudio
python -m pip install torch torchvision torchaudio \
  --index-url https://download.pytorch.org/whl/${CUDA_TAG}

# conda 环境的等价写法(cuda 版本号同样按驱动能力替换)
conda install pytorch torchvision torchaudio pytorch-cuda=${CUDA_VER} \
  -c pytorch -c nvidia

如果读者用的是容器,还要确认启动参数带上了 GPU 直通,否则容器内的 is_available() 必然是 False,换多少次包都没用。可先运行 docker run --rm --gpus all <镜像> nvidia-smi 看容器内是否能看到显卡,能看到再谈装哪个 torch。公司内网无法访问外部索引时,把包下载到本地目录后用 --find-links 指向该目录,索引地址换成内网镜像即可,命令结构不变。

PyTorch安装后发现CUDA不可用怎么切换GPU版本

改完后怎么验证

验证要分两层:先确认 torch 认到设备,再确认一次真实的显存分配能跑通。只看 is_available() 为 True 还不够,某些环境下能枚举设备但在分配张量时失败,通常是驱动与 runtime 的兼容问题。

python -c "import torch; assert torch.cuda.is_available(), 'cuda still unavailable'; t = torch.zeros(3, device='cuda'); print(t.device); print(torch.cuda.get_device_name(0)); print('cudnn:', torch.backends.cudnn.version())"

# 另开一个终端,观察是否有进程占用显存
nvidia-smi

预期信号有三个:t.device 打印出 cuda:0;get_device_name(0) 打印出实际的显卡型号,而不是空串;在张量分配的那一瞬间,另一个终端的 nvidia-smi 里出现对应的 python 进程和显存占用。若这三条都成立,可以认为 GPU 版本切换完成,接着再跑项目自己的启动脚本或一个 epoch 的训练做业务侧确认。若 is_available() 仍为 False,回到第一节的四项信息重新比对,多半是版本标签选高了。

容易忽略的边界

驱动对 CUDA 版本的兼容是“向下兼容、向上不保证”,驱动版本偏低时装高 CUDA runtime 的 torch 会静默退化为不可用。此时两条路:换低 CUDA 标签的 PyTorch,或者升级显卡驱动,升级驱动在共享服务器和多用户机器上要先确认权限和影响范围,不建议在跑着任务的机器上直接操作。

常见坑还有几类:pip 和 conda 混装导致同一环境里存在两份 CUDA 运行库,import torch 时加载到旧版本的 libcudart 或 libcublas;LD_LIBRARY_PATH 里残留系统 CUDA 目录,覆盖了 wheel 自带的库;WSL 或容器内没有正确直通 /dev/nvidia* 设备;多卡机器上 CUDA_VISIBLE_DEVICES 被上层脚本设成了空值。这些情况下 torch 版本本身没问题,需要先排掉环境变量和设备可见性。

回退建议:如果驱动版本受管控一时无法调整,就先装与驱动匹配的较低 CUDA 标签版本,功能上通常够用;如果环境已经装满其他依赖、改动风险大,最省事的办法是新建一个干净的虚拟环境,把 GPU 依赖单独放进去,而不是在原环境里反复卸载重装。确实拿不到 GPU 时,先装 CPU 版保证代码路径可跑,把设备选择抽成配置项,等驱动或权限到位再切换回 GPU 版,避免因为环境问题阻塞其他工作。