☰
PyCharm+PyTorch+CUDA环境搭建:GPU不可用排查与验证
2026/9/30 3:27:05 网站建设 项目流程

显卡插上、驱动也装好了,nvidia-smi能正常出画面,结果在 PyCharm 里敲下import torch再跟一句torch.cuda.is_available(),回车返回一个False——这个瞬间大概是所有做深度学习的朋友都经历过的。更气人的是,同样这几行代码,在另一个同学机器上、甚至在你自己的另一个 conda 环境里,跑得好好的。问题往往不出在 PyTorch 本身,而出在前面那几步:驱动版本、CUDA 运行时版本、PyTorch wheel 的编译版本、Python 解释器版本,这四个东西只要有一个错位,GPU 就用不上。

这篇内容就是把这四个东西的对应关系捋清楚,然后从零走一遍 PyCharm + CUDA + PyTorch 的完整搭建流程:包括怎么根据自己显卡驱动反推该装哪个 CUDA 版本的 PyTorch、conda 环境怎么建、--index-url该写什么、怎么验证 GPU 真的被调用了、PyCharm 的解释器和终端为什么会"打架"、以及下载中断报invalid compressed data这类让人抓狂的问题怎么收尾。适合刚拿到带独显机器的同学,也适合从别的框架转过来、想一次把环境理顺的人。

1. 版本这盘棋先摆正:驱动、CUDA、PyTorch 三者的依赖不是"装最新就行"

很多人装机失败的第一步,是默认"版本越新越好"。显卡驱动装最新的、CUDA Toolkit 下最新的、PyTorch 也 pip 装最新的,看起来很合理,实际上这三者的依赖方向是单向的:PyTorch 的 wheel 决定了它需要哪个 CUDA 运行时,CUDA 运行时又决定了它最低需要哪个驱动。你反过来硬凑,就会出现 wheel 里内嵌的 CUDA 运行时比驱动支持的版本还高,加载时直接报CUDA driver version is insufficient for CUDA runtime version。

1.1 nvidia-smi 右上角那行 CUDA Version,说的是驱动能力上限

先跑一条命令:

nvidia-smi

输出右上角会有一行CUDA Version: 12.4之类的字样。这里有个极容易被误读的点:这行不是"你装了 CUDA 12.4",而是"你当前这个驱动最高能支撑到 CUDA 12.4 的运行时"。也就是说,它是个上限值,不是已安装值。你去which nvcc可能什么都找不到,但nvidia-smi一样显示 CUDA Version,这不矛盾。

Linux 上还可以再交叉验证一下驱动本身的版本:

cat /proc/driver/nvidia/version

Windows 上则去 NVIDIA 控制面板的"系统信息"里看驱动版本号。把这个数字记下来,后面选 PyTorch 版本时全靠它。

1.2 同大版本内的次版本兼容,到底能省多少事

CUDA 从 11 开始引入了次版本兼容(Minor Version Compatibility)的概念:同一个大版本号内,低版本驱动可以运行高次版本的 CUDA 运行时。翻译成人话就是,你的驱动只要支持 CUDA 12.0,原则上就能跑 12.1、12.4 甚至 12.6 的运行时,不需要为了每一个次版本去换驱动。

但这条规则有边界,别当成万能护身符:

  • 只保证"跑得起来",不保证性能曲线和官方文档完全一致,个别依赖新驱动特性的库仍可能出问题;
  • 跨大版本(比如驱动只支持 11.x,你却要跑 12.x 的运行时)不适用,会直接报错;
  • 如果 wheel 里带了 PTX 需要即时编译的算子,旧驱动可能无法 JIT 出目标架构的代码。

所以实操建议是:驱动装到比目标 CUDA 大版本的最新次版本略微高一档的位置,留点余量。比如你打算用 CUDA 12.4 的 PyTorch,驱动版本尽量选 550 以上,别卡在及格线上。

1.3 一张能直接抄的版本对照表

下面这张表是我自己装机时整理的常用搭配,覆盖近两年主流版本。注意 PyTorch 官方的pip索引后缀(cu118、cu121这种)就等于它内嵌的 CUDA 运行时版本。

PyTorch 版本可选 CUDA 后缀建议驱动版本下限支持的 Python 区间
2.0 / 2.1cu117 / cu118 / cu121450+ / 520+3.8 – 3.11
2.2 / 2.3cu118 / cu121520+3.8 – 3.12
2.4 / 2.5cu118 / cu121 / cu124550+(用 cu124 时)3.9 – 3.12
2.6cu118 / cu124 / cu126560+(用 cu126 时)3.9 – 3.13
2.7cu118 / cu126 / cu128570+(用 cu128 时)3.9 – 3.13
2.8cu126 / cu128 / cu129570+3.10 – 3.13

注意:这张表是为了让你快速定位,真正下单前一定去 PyTorch 官网首页的 Get Started 选择器上核一遍。官方选择器会同时给出 conda 和 pip 两条命令,并且只列出当前版本真实存在的后缀组合,比自己猜靠谱。

还有一个绝大多数教程没讲清楚、但极其关键的点:用 pip 装 PyTorch,你不需要单独安装 CUDA Toolkit,也不需要单独装 cuDNN。wheel 包里已经把对应的 CUDA 运行时库和 cuDNN 一起打进去了。很多人上来先下几个 GB 的 CUDA Toolkit 安装包,装完发现 PyTorch 那边一个字节都没用上——白折腾。什么时候才需要完整的 Toolkit?只有你要编译自定义 CUDA 算子、或者装flash-attn、deepsparse这类需要本地 nvcc 的包时才需要。普通训练推理,跳过。

2. 底座环境怎么铺:Python 解释器、虚拟环境与下载通道

版本配对之后,接下来是环境本身。这一步的坑不在技术难度,而在"图省事"。

2.1 别在系统 Python 上装 torch,这是我踩过最贵的一个坑

我早期做过一件蠢事:直接在系统的 Python 3.9 上pip install torch,当时能跑,后来要换一个 CUDA 版本,pip uninstall又卸不干净,最后系统里一堆半残的包,某个 CLI 工具直接起不来,重装系统才彻底解决。

正确做法是永远用独立虚拟环境。理由不只是"干净",还有三条很实际的:

  • 版本隔离:项目 A 要 CUDA 11.8 的 torch,项目 B 要用 CUDA 12.4 的,同一个解释器里不可能共存,虚拟环境天然解决;
  • 可复现:换机器时导出环境文件就能重建,不用回忆当初装了什么;
  • 可整包删除:出问题了直接conda env remove删目录,不留任何后遗症。

2.2 conda 建环境的具体命令与目录规划

我的习惯是把所有环境集中放在一个明确目录下,不要让它散落在用户目录里找不着。以 Windows 为例,Anaconda 默认装在D:\Anaconda3,环境目录就是D:\Anaconda3\envs。

# 建环境,Python 版本对齐 PyTorch 的支持区间 conda create -n torch24 python=3.11 -y # 激活(Windows 用 conda activate,若报错需要先 conda init) conda activate torch24 # 确认当前用的是哪个 python,这一步千万别省 python -c "import sys; print(sys.executable)"

最后那条命令是整个流程里最值钱的一条。后面 PyCharm 里配解释器,路径就是它打印出来的这个东西。没有意外的话会输出类似D:\Anaconda3\envs\torch24\python.exe的路径。

Linux 和 macOS 上命令一致,环境目录通常在~/miniconda3/envs/或~/anaconda3/envs/,用conda info --envs能看到所有环境及其绝对路径。

如果你不喜欢 conda,用标准库自带的 venv 也完全可行:

python -m venv D:\venvs\torch24 D:\venvs\torch24\Scripts\activate

venv 的优点是轻,缺点是装某些科学计算包时要自己处理编译依赖,而且没法像 conda 那样顺带装非 Python 的二进制品。做深度学习,我还是推荐 conda。

2.3 下载通道:镜像源、缓存目录与超时重试

PyTorch 的 wheel 动辄两三个 GB,网络通道直接决定你这一步是十分钟还是两小时。我一般做三件事。

第一,给 conda 配国内镜像源,改~/.condarc(Windows 是C:\Users\你的用户名\.condarc):

channels: - defaults show_channel_urls: true default_channels: - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r

第二,pip 用-i临时指定源,而不是全局改配置。因为 PyTorch 官方 wheel 只在自己的索引上有,全局改了源之后装 torch 又要绕回来,容易搞混:

# 装普通包时走镜像 pip install numpy pandas -i https://pypi.tuna.tsinghua.edu.cn/simple # 装 torch 时明确走官方索引 pip install torch --index-url https://download.pytorch.org/whl/cu121

第三,把 pip 缓存目录设在空间充足的盘上,避免 C 盘被几个 GB 的 wheel 撑爆:

pip config set global.cache-dir D:\pipcache

提示:如果下载过程中频繁超时,加--timeout 120 --retries 5。这两个参数看着不起眼,但在跨国链路里能把"重来三次"变成"一次过"。

3. 装 PyTorch 的实操:索引地址、wheel 选择与离线兜底

环境准备好了,真正动手装 torch。这一步最常见的结果是"装上了但装错了"——装成 CPU 版,用的时候才发现。

3.1--index-url指向哪里,决定了你拿到的是 GPU 版还是 CPU 版

PyTorch 的包分发机制很特殊:PyPI 官方仓库上的torch默认是 CPU 版本。你如果只敲pip install torch,在多数平台上下到的就是 CPU 版,装完torch.cuda.is_available()必然是False,而且一点报错都不会有,非常隐蔽。

要拿 GPU 版,必须显式指定 PyTorch 自己的索引:

# CUDA 12.1 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 # CUDA 11.8 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # CUDA 12.4 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124 # 纯 CPU(没独显或只需要跑推理) pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu

torchvision和torchaudio的版本是跟torch绑死的,三个必须一起装、一起升、一起降。我见过太多次"单独pip install -U torchvision"导致版本不匹配报RuntimeError: operator torchvision::nms does not exist的案例。要么三个一起走,要么别动。

3.2 从 wheel 文件名反推它是不是你要的那个

下载时可加-v看进度详情,或者直接看 pip 缓存里的 wheel 文件名。一个典型的文件名长这样:

torch-2.4.1+cu124-cp311-cp311-win_amd64.whl

拆开读:

  • torch-2.4.1—— PyTorch 版本;
  • +cu124—— 内嵌 CUDA 12.4 运行时。如果这里没有+cuXXX后缀,就是 CPU 版;
  • cp311—— 对应 CPython 3.11。你如果是 3.12 的环境下到了cp311的包,说明索引里的 Python 版本对应关系搞错了;
  • win_amd64—— Windows 64 位。Linux 上是manylinux_x86_64。

记住这个命名规则,你就再也不会被"我到底装的是哪个版本"困扰了。装完之后用一条命令复核:

import torch print(torch.__version__) # 2.4.1+cu124 print(torch.version.cuda) # 12.4 print(torch.backends.cudnn.version()) # 例如 90100

3.3 下载中断报 "invalid compressed data" 的完整处理链路

这个报错原文是:

gzip: stdin: invalid compressed># 只下载不安装,把依赖包一起下到本地目录 pip download torch torchvision torchaudio \ --index-url https://download.pytorch.org/whl/cu121 \ -d D:\wheels

然后把整个D:\wheels拷到目标机器,离线安装:

pip install --no-index --find-links=D:\wheels torch torchvision torchaudio

--no-index是关键,它强制 pip 不去访问任何在线索引,避免内网环境下卡在超时上。另外,pip download时要保证下载机器的 Python 版本和位数跟目标机器完全一致,否则下到的 wheel 标签对不上,装的时候会提示 "not a supported wheel on this platform"。

4. 装完必须验收:让 GPU 真正跑起来的几个检查点

装完不验证,等于没装。我见过太多人在 PyCharm 里跑了一个月才发现自己一直在用 CPU,只是代码里没打印过设备信息。

4.1 is_available() 返回 False 的排查顺序

先跑一个最小脚本:

import torch print("torch:", torch.__version__) print("cuda build:", torch.version.cuda) print("available:", torch.cuda.is_available()) print("count:", torch.cuda.device_count())

如果available是False,按下面这个顺序查,别乱试:

检查项命令/方法判断依据
是不是 CPU 版 wheel看torch.__version__有没有+cuXXX没有后缀就是 CPU 版,重装
驱动是否正常nvidia-smi报错或看不到设备,先修驱动
驱动版本是否够对比第 1 节的版本表低于下限就升驱动
环境里是否装了多份 torchpip list | findstr torch出现重复来源要清干净重装
是否被环境变量屏蔽看CUDA_VISIBLE_DEVICES值被设成-1或空会导致不可见
是不是 conda 装的 cudatoolkit 混进来了conda list | grep cudaconda 渠道和 pip 渠道别混着装

第三条和第六条是最常见的两个隐形杀手。特别是混装:有人先conda install pytorch cudatoolkit=11.8,后来又pip install torch,两套东西在同一个环境里各占一半,报错信息往往指向一个莫名其妙的 DLL 找不到。

4.2 用一次矩阵乘法给显卡"打卡"

is_available()为 True 只是说明驱动和运行时握手成功,不代表计算真的落在 GPU 上。加一步实测:

import torch import time dev = torch.device("cuda:0") a = torch.randn(4096, 4096, device=dev) b = torch.randn(4096, 4096, device=dev) torch.cuda.synchronize() # 等前面的 kernel 排空 t0 = time.time() for _ in range(20): c = a @ b torch.cuda.synchronize() # 关键:不同步的话计时会把异步执行算成 0 秒 t1 = time.time() print("elapsed:", round(t1 - t0, 3), "s") print("device:", torch.cuda.get_device_name(0))

这里的torch.cuda.synchronize()是个必须提的点:CUDA 的 kernel 是异步下发的,CPU 把任务丢进队列就返回了。你不加同步,计时结果可能只有零点几毫秒,看起来快得离谱,其实是没算完。这个坑在做性能对比时特别容易踩。

4.3 顺便把显存、算力和设备编号也记下来

print("显存(GB):", torch.cuda.get_device_properties(0).total_memory / 1024**3) print("算力:", torch.cuda.get_device_capability(0)) # 例如 (8, 6) print("设备数:", torch.cuda.device_count())

算力这个值(Compute Capability)后面会用到。它是显卡的硬件代号,比如 8.6 对应 RTX 30 系、8.9 对应 RTX 40 系、12.0 对应更新的架构。PyTorch 的 wheel 里预编译了针对特定算力的 kernel,如果你的卡算力很新,而 wheel 编译时还没覆盖,就可能出现 kernel 找不到、只能退回慢速路径的情况。这也是为什么新卡往往要用更新的 PyTorch 版本。

顺便说一句,nvcc --version显示的版本和torch.version.cuda不一致是完全正常的:前者是你系统里可能装的 Toolkit 编译器版本,后者是 wheel 内嵌的运行时版本。用 pip 装 torch 的场景下,两者本来就不需要一致,别为此去返工。

5. PyCharm 侧收尾:解释器、终端和运行配置里的隐形错位

前面所有步骤都在命令行里做的,PyCharm 这一层是很多人"命令行明明可以,PyCharm 里就是不行"的根源。

5.1 解释器路径选错,前面全白干

PyCharm 打开项目后,第一件事是配解释器:File → Settings → Project: 项目名 → Python Interpreter → Add Interpreter → Add Local Interpreter → Conda Environment → Existing environment,然后手动指到第 2.2 节打印出来的那个python.exe。

有个细节值得强调:PyCharm 有时会自作聪明地推荐"新建一个环境"。如果你已经用命令行建好并装好了 torch,就一定要选Existing environment,不要让它新建——新建出来的环境是干净的,torch 得重装一遍。我自己就中过招,配完发现is_available()是 False,来回查了半天版本,最后发现是 PyCharm 悄悄建了个新环境。

配好之后立刻在 PyCharm 底部的 Python Console 里跑一遍:

import sys, torch print(sys.executable) print(torch.__version__, torch.cuda.is_available())

第一行输出的路径必须跟你在 Settings 里选的一致。不一致说明 PyCharm 用的还是别的解释器。

5.2 PyCharm 的 Terminal 和 Run 用的可能不是同一个 Python

这是最隐蔽的一类问题:PyCharm 内置 Terminal(Alt+F12 打开的那个)默认会尝试激活当前项目的虚拟环境,但这个激活行为在 Windows 上经常因为执行策略或者 shell 类型而失效。失效的表现是,你在 Terminal 里pip install torch,装到了 base 环境;然后点 Run 按钮运行脚本,用的却是项目环境——于是"我明明装了,怎么还是报 ModuleNotFoundError"。

处理办法:

  • 在Settings → Tools → Terminal里确认Activate virtualenv是勾选状态;
  • 打开 Terminal 第一件事永远是敲where python(Windows)或which python(macOS/Linux),确认路径;
  • 如果 Terminal 死活不激活,就直接用绝对路径调用:D:\Anaconda3\envs\torch24\Scripts\pip.exe install ...。

提示:装包这件事,我更推荐统一在外部终端里做,做完回 PyCharm 里跑代码。因为 PyCharm 的包管理界面在做大版本替换(比如 torch 从 CPU 版换成 GPU 版)时,偶尔会出现卸载不干净的情况。

5.3 运行配置里的工作目录与环境变量

Run → Edit Configurations里有两个常被忽略的字段。

Working directory:默认是项目根目录,这决定了代码里相对路径的基准。如果你的数据集路径写的是./data/train,而工作目录被改到了别处,就会报文件找不到。做深度学习项目时,我习惯在代码里统一用Path(__file__).parent来定位资源,不依赖工作目录,换到哪台机器都不会错。

Environment variables:多卡机器上必用。指定只用第 0 号卡:

CUDA_VISIBLE_DEVICES=0

或者只用第 2、3 号卡:

CUDA_VISIBLE_DEVICES=2,3

注意这个变量是在进程启动前生效的,代码运行中再改没用。另外设完之后,程序里看到的卡号会被重新编号,原来的 2 号卡会变成cuda:0,这点在写多卡代码时容易搞混。

还有一处细节:PyCharm 的 Python Console 每次启动都会新开一个解释器进程,如果你在 Console 里import torch之后发现显存被占着,那不是内存泄漏,是 Console 进程还在。关掉 Console 标签或者点停止按钮就行。

5.4 几个高频报错:VC++ 14.0、DLL load failed、cuDNN 相关

下面这几个报错,我在不同机器上都遇到过,按报错原文整理一下处理思路。

error: Microsoft Visual C++ 14.0 is required—— 这个通常出现在 pip 找不到预编译 wheel、转而尝试从源码编译时。Windows 上的解法有两条:一是确认下的 wheel 标签匹配(win_amd64+ 正确cpXXX),能命中预编译包就不会触发编译;二是确实需要编译时,装 Visual Studio Build Tools,勾选 "使用 C++ 的桌面开发" 工作负载,装完重启终端。优先走第一条路,编译一遍 torch 源码动辄半小时起步,没必要。

OSError: [WinError 126] 找不到指定的模块或DLL load failed—— 十有八九是环境里混了多个来源的 torch,或者缺了某个运行库。先pip list看有没有重复条目,conda list也看一遍,确认只有一个来源;然后彻底卸干净重装:

pip uninstall torch torchvision torchaudio -y pip cache purge pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

cuDNN 相关的版本警告—— 如果报的是 cuDNN 版本不匹配,先用torch.backends.cudnn.version()看 wheel 内嵌的版本,再确认自己没有手动装过一个不同版本的 cuDNN 并且把它加进了 PATH。两者冲突时,以 wheel 内嵌的为准,别去动它。

out of memory但显存看着还剩不少—— 常见原因是碎片化加上一次性申请大块连续显存。可以先torch.cuda.empty_cache(),再降低 batch size;如果模型本身大,用梯度累积把等效 batch 凑回来,比直接砍 batch 更划算。

6. 多环境共存与换机迁移:别让第二台机器重来一遍

单个环境搭好只是开始。真正消耗时间的是第二台机器、第三个项目、第四个 CUDA 版本。

6.1 单机多套 CUDA 时路径优先级怎么排

用 pip 装 torch 的话,即使不装 Toolkit 也能跑训练,所以多版本共存的问题其实没那么严重——每个虚拟环境里的 torch 自带自己那份运行时,互不干扰。这是虚拟环境最大的价值之一。

但如果你需要编译自定义算子,就绕不开CUDA_HOME/CUDA_PATH这个环境变量。规则是:

  • Linux 上,编译器找的是CUDA_HOME指向目录下的bin/nvcc,同时动态库搜索路径由LD_LIBRARY_PATH或/etc/ld.so.conf.d/下的配置决定;
  • Windows 上,CUDA_PATH决定默认版本,PATH 里靠前的bin目录会覆盖靠后的;
  • 多个版本共存时,不要把它们都塞进全局 PATH,而是按项目在虚拟环境激活脚本里临时设置:
conda activate torch24 export CUDA_HOME=/usr/local/cuda-12.4 export PATH=$CUDA_HOME/bin:$PATH

这样切换环境时nvcc会自动跟着换,比全局改 PATH 干净得多。

6.2 环境导出与换机复现的清单

导出环境我一般同时留两份,因为单独一份都不够:

# 含构建号的完整导出,同架构复现最准 conda env export > environment.yml # 不含构建号,跨平台兼容性更好 conda env export --no-builds > environment-nobuilds.yml # pip 层级的精确版本 pip freeze > requirements.txt

environment.yml里带上--no-builds那份更适合换机,因为构建号跟具体的操作系统和平台强绑定,带上了在另一台机器上大概率解析失败。

重建时:

conda env create -f environment-nobuilds.yml # 或者只重建 Python 环境,再按 requirements 装包 pip install -r requirements.txt --index-url https://download.pytorch.org/whl/cu121

除了环境文件,我还会在一个SETUP.md里记三样东西:nvidia-smi的完整输出、torch.__version__与torch.version.cuda、以及显卡的 Compute Capability。这三行信息一旦留档,半年后回来重装环境能省下大半天。

6.3 新显卡的算力代差问题

最后一件事,关于新卡。显卡架构的更新速度比 PyTorch 的发布节奏快,新架构刚上市时,老版本的 PyTorch wheel 里可能没有针对它预编译的 kernel。表现是能跑,但速度明显不对,或者某些算子在运行时报找不到实现。

处理办法很直接:换用更新的 PyTorch 版本配更新的 CUDA 后缀。比如 50 系显卡对应的算力代号较高,需要较新的 CUDA 12.8 这一档的 wheel 才能完整覆盖。

如果你已经装好了但想确认覆盖情况,可以跑一个小测试,把常见算子过一遍:

import torch x = torch.randn(1024, 1024, device="cuda") _ = x @ x.t() _ = torch.nn.functional.conv2d( x.view(1, 1, 1024, 1024), torch.randn(1, 1, 3, 3, device="cuda") ) _ = torch.nn.functional.softmax(x, dim=-1) torch.cuda.synchronize() print("ops ok, capability:", torch.cuda.get_device_capability(0))

没有异常抛出,基本可以认为常用路径都能正常走通。

我个人在实际操作中的体会是,这套流程里最值钱的不是任何一条命令,而是"先确定版本,再动手装"这个顺序。绝大多数的环境问题,本质都是版本错配,而版本错配的根源是跳过了nvidia-smi那一步直接开始下安装包。把第 1 节那张表和自己机器的实际情况对一遍,后面所有的命令都会顺得像走直线。另外补一句,requirements.txt里记得把--index-url那一行也写进去(或者单独写个安装脚本),不然过几个月你自己都会忘记当初是从哪个索引装的 GPU 版。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询