尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

CUDA 11.3 配 PyTorch-GPU:一次装对与验证排错指南

CUDA 11.3 配 PyTorch-GPU:一次装对与验证排错指南 装 CUDA 和 PyTorch 最让人心态崩掉的时刻从来不是命令敲错而是你按着教程一步步走完nvcc -V漂漂亮亮地打出release 11.3nvidia-smi也一切正常结果在 Python 里敲下torch.cuda.is_available()屏幕回你一个冷冰冰的False。更气人的是这个False背后可能有五六种完全不同的原因——装成了 CPU 版、驱动太老、环境变量串了、conda 与 pip 混着装了两套、Windows 上缺了个运行库——每一种的修法都不一样瞎试只会把环境越搞越乱。这篇内容只聊一件事CUDA 11.3 搭配 PyTorch-GPU 版本这条路怎么一次装对、装稳、装完能验证。之所以专门拎出 11.3 这个版本是因为它在很长一段时间里是国内 GPU 机器上出现频率极高的一个组合——不少实验室的老服务器、租来的 GPU 实例、以及一批需要在旧驱动上跑起来的项目代码都锁死在 cu113 上。你可能会遇到接手一台别人装了一半的机器给公司内网的一台离线服务器配深度学习环境或者只是自己攒了台带独显的主机想跑个训练脚本。适合谁看手里有 NVIDIA 显卡、正在第一次搭 PyTorch GPU 环境的人已经装过一次但is_available()始终为 False、想搞清楚到底哪一步错了的人以及需要在离线或受限网络环境下复现一套环境的运维和工程同学。全文以 CUDA 11.3 与 PyTorch cu113 为主线但里面关于版本匹配、验证思路和排错顺序的方法换到任何 CUDA 版本上都是通用的。1. 先把版本地图铺开CUDA 11.3 到底能配哪几版 PyTorch大部分人装环境翻车根源在于把 CUDA 理解成了一个装最新版总没错的东西。事实上 CUDA 在 PyTorch 这条链路里本质上是一个被三方NVIDIA 驱动、CUDA 运行时、PyTorch 预编译轮子共同约定的版本号任何一个环节不认这个号整条链就断。所以在敲任何命令之前得先把这几个概念之间的从属关系理清楚。1.1 驱动、CUDA Runtime、cuDNN、PyTorch 的四层从属关系# 第一层显卡驱动决定了你这台机器「最高能跑」哪个 CUDA 大版本 nvidia-smi # 右上角那个 CUDA Version: 11.x 是驱动支持的上限不是当前装的版本 # 第二层CUDA Toolkit / Runtimenvcc、libcudart、头文件都在这 nvcc -V # 只有装了完整 Toolkit 才有这个命令 # 第三层cuDNN深度学习的卷积、RNN 等算子加速库 # 第四层PyTorch 轮子它是用某个特定 CUDA 版本编译出来的cu113 / cu116 / cu117 ...关键点是nvidia-smi里显示的 CUDA Version 是驱动能支持的最高版本不是你已经装了什么。很多人看到那里写着 11.3就以为机器上已经有 CUDA 11.3 了直接去pip install torch结果torch.version.cuda打印出来是None。它俩根本是两回事。还有一个容易被忽略的机制叫 minor version compatibilityCUDA 11.x 系列内部做了次版本兼容也就是说只要驱动是 R450 以上的 11.x 驱动就能跑用 11.0 到 11.8 任意次版本编译出来的程序。这条规则的实际意义是——你的驱动不需要精确等于 CUDA 11.3只要落在 11.x 这个大的范围内通常就能跑起来。1.2 一份可以直接照抄的 cu113 兼容对照表用 CUDA 11.3 编译的 PyTorch 轮子官方一共覆盖了三个小版本系列。这张表我建议直接存下来选版本的时候对着找PyTorch 版本torchvisiontorchaudio官方支持的 Python轮子后缀1.10.0 / 1.10.1 / 1.10.20.11.1 / 0.11.20.10.0 / 0.10.13.6 – 3.9cu1131.11.00.12.00.11.03.7 – 3.10cu1131.12.0 / 1.12.10.13.0 / 0.13.10.12.0 / 0.12.13.7 – 3.10cu113从这张表能读出三个很实用的结论第一Python 版本别用太新的。如果你打算用 1.10.xPython 就老老实实选 3.8 或者 3.9。3.10 在 1.10 上是没有官方轮子的pip 会一路往回找源码包最后给你一堆编译错误。我在实际项目里基本固定用 3.8兼容性最舒服。第二torch、torchvision、torchaudio 三个包的版本必须成套。单独升级 torch 而不管 torchvisionimport torchvision时会抛RuntimeError: operator torchvision::nms does not exist之类的错这不是环境坏了是版本对不上。装的时候三个写在同一行让 pip 或 conda 一次性解析。第三cu113 的时间窗口比想象中窄。它主要对应 2021 年底到 2022 年年中那几个版本正因为如此凡是锁死 cu113 的项目往往也意味着它的依赖链整体偏旧——这时候千万不要手贱去升级别的包。1.3 为什么驱动装高点、CUDA 随便装是个危险想法新人最常听到的一句话是驱动装最新的就行这话对一半。新驱动确实向下兼容但它兼容的是运行不兼容编译。如果你后面要用nvcc编译自定义算子比如各种检测框架里的 DCNv2、可变形卷积、或者量化相关的扩展编译时的 CUDA 版本和 PyTorch 轮子的 CUDA 版本不一致链接阶段大概率会报一堆 undefined symbol。我见过太多训练能跑、一装自定义算子就崩的案例根因全在这里。所以正确的思路是先确定 PyTorch 需要哪个 CUDA 版本再倒推去准备对应的 Toolkit 和驱动。而不是反过来先把 CUDA 装成某个版本再去碰运气找能配上的 PyTorch。2. 动手前的体检三条命令判断机器能不能吃下 cu113在下载任何安装包之前花五分钟做一次体检能省掉后面几小时的无用功。这一步的关键不是看机器好不好而是判断这台机器应该走哪条安装路线——是升级驱动走标准路线还是保持驱动不动、把 CUDA 降到别的版本去。2.1 nvidia-smi 里真正需要看的只有三行nvidia-smi输出信息很长但值得关注的是这三处Driver Version驱动版本号。这是决定能不能上 CUDA 11.3 的硬指标。CUDA 11.3 官方要求 Linux 侧驱动不低于 465.19.01Windows 侧不低于 465.89。结合前面说的次版本兼容机制Linux 上 R450.80.02 及以上、Windows 上 452.39 及以上的驱动理论上也能跑 11.3 的程序但部分特性会受限。CUDA Version右上角驱动支持的上限。这个数字只要大于等于 11.3就说明驱动这关过了不用去管机器上是否真的装了 CUDA。显存与 GPU 型号顺便确认一下卡是不是 NVIDIA 的、算力等级够不够。算力代号低于 sm_35 的老卡比如早期的 Kepler 架构在新的 PyTorch 轮子里已经找不到对应编译的 kernel跑起来会提示算力不匹配。顺手再敲两条确认系统层面没有坑lspci | grep -i nvidia # Linux确认内核真的认到了卡 ls /usr/local/ | grep cuda # 看看是不是已经存在旧版本的 CUDA 目录第二条命令很有必要。很多二手服务器或者别人用过的实例上/usr/local/cuda-10.2、/usr/local/cuda-11.0都还躺着而/usr/local/cuda这个软链接指向的是其中一个。如果不先摸清这个状态直接装 11.3最后你的nvcc和 Python 里的torch用的很可能不是同一套报错信息会非常迷惑。2.2 驱动过老时的两条路选哪条取决于项目允许你改什么体检结果如果显示驱动版本低于要求你有两个选择而且这个选择不能拍脑袋定路线 A升级驱动。适合你有 root 权限、机器上没有其他在跑的关键业务、也不担心重启的场景。升级驱动的好处是一次到位后续想换任何 CUDA 版本都方便。注意 Linux 上如果服务器同时装了开源 nouveau 驱动要先屏蔽掉否则装完重启会卡在登录界面黑屏。路线 B降 CUDA 版本。适合共享服务器、无 root 权限、或者驱动升级受管控的环境。这时候就不要死磕 11.3 了去看你的 PyTorch 版本有没有对应的更低版本轮子。举个例子PyTorch 1.10 除了 cu113还有 cu102 和 cu111 的轮子如果你的驱动只到 460 甚至 450那选 cu111 而不是硬上 cu113成功率会高得多。这里有个判断经验如果这台机器是长期使用的生产机优先升驱动如果只是临时租一两周跑个实验优先换 CUDA 版本。因为升级驱动要承担重启和设备不可用的风险而换 CUDA 版本只影响你当前这个环境的安装命令代价小得多。2.3 Python、conda 与编译器三个容易被完全忽略的前置条件除了显卡还有三个东西必须提前确认Python 版本。python --version看一眼。前面表格里写得很清楚用 1.10.x 就别超 3.9。另外如果你用的是 conda 环境务必先conda activate到目标环境再执行安装否则包会装到 base 环境里后面再想切回来就麻烦了。conda 是否可用。conda --version。没有的话先装 Miniconda比 Anaconda 轻量得多Anaconda 装完动辄 3 GB 以上很多人根本没用到那么多预装包。gcc 版本仅编译场景需要。CUDA 11.3 官方支持的 GCC 上限是 GCC 10。如果你用的是 Ubuntu 22.04 自带 GCC 11在编译自定义算子时会收到unsupported GNU version的报错。解决办法是装个 gcc-9 或者 gcc-10然后在编译前指定export CC/usr/bin/gcc-9 export CXX/usr/bin/g-9这一步只在你需要编译扩展的时候才重要。如果只是跑现成的模型可以跳过。但提前知道这个坑的存在能让你在遇到时不用满世界搜报错。3. 装 CUDA Toolkit 11.3 的三种路径以及各自的取舍现在的关键问题来了到底要不要装完整的 CUDA Toolkit答案取决于你怎么用 PyTorch。如果你只用 pip 或 conda 装官方轮子、跑现成的模型和训练那么你根本不需要单独装 CUDA Toolkit——PyTorch 的 GPU 轮子里已经把 CUDA 运行时库打包进去了安装包之所以有一两个 GB 那么大就是因为里面塞了这些东西。这种情况下装 Toolkit 纯属多余还容易引入环境变量冲突。但你只要涉及下面任意一种情况就老老实实装用nvcc编译自定义 CUDA 扩展用 TensorRT、DeepSpeed 之类需要自己编译的组件或者需要在命令行直接调用 CUDA 工具链。三种安装路径各有适用场景。3.1 runfile 安装最大的价值在于可以只装 Toolkit、不装驱动这是我最推荐的离线或半离线场景方案。从官方归档页面下载 runfile文件名类似cuda_11.3.1_465.19.01_linux.run注意这个文件名里带着驱动版本号说明它默认会把驱动一起装上。这在已经装过驱动的机器上会直接出问题——新版驱动覆盖旧版运气不好就把显卡搞成不可用还得进恢复模式救。# 关键一步把驱动和 Toolkit 拆开只装 Toolkit sudo sh cuda_11.3.1_465.19.01_linux.run # 出现交互界面后务必把 Driver 那一项的勾去掉 # 只保留 CUDA Toolkit 11.3 / CUDA Samples 等如果你走的是静默安装脚本化部署时常用参数可以这样写sudo sh cuda_11.3.1_465.19.01_linux.run \ --silent \ --toolkit \ --toolkitpath/usr/local/cuda-11.3 \ --override--toolkit明确表示只装工具链--driver就不出现。--toolkitpath指定独立目录方便日后和别的版本共存。--override是告诉安装器忽略编译器版本检查——如果机器上的 GCC 比 CUDA 11.3 支持的更新不加这个参数会直接被拦下来。还有一个实用细节runfile 在安装前会检测 X server 是否在运行因为装驱动需要关掉图形界面。因为我们不装驱动所以即使图形界面开着也能顺利跑完这是它比 deb 方式方便的地方。3.2 deb 网络安装省事但要处理签名密钥Ubuntu 用户如果网络通畅可以用网络安装源的方式wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-ubuntu2004.pin sudo mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600 sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/7fa2af80.pub sudo add-apt-repository deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/ / sudo apt-get update sudo apt-get install cuda-toolkit-11-3注意apt-key这个方式现在已经被标记为废弃而且 NVIDIA 的仓库签名密钥在 2022 年做过一次轮换用旧的 key ID 会直接报NO_PUBKEY或签名验证失败。遇到这种情况需要改成把密钥下载下来放到/usr/share/keyrings/再在源里用signed-by引用或者干脆换用 runfile 方式绕过这个麻烦。cuda-toolkit-11-3这个包名也很讲究cuda是全家桶装完一大串东西还会顺手把驱动带上cuda-toolkit-11-3只装工具链cuda-runtime-11-3更小只装运行时。推荐用cuda-toolkit-11-3语义清楚、副作用小。3.3 conda 装 cudatoolkit最轻但有一个必须知道的限制如果你嫌系统级安装麻烦conda 也提供 CUDA 运行时conda install cudatoolkit11.3 -c conda-forge它的优点是整个 CUDA 运行时被限制在 conda 环境内部删环境时干干净净不会在/usr/local留下任何痕迹。适合不想动系统、只在本环境中跑 PyTorch 的场景。但有个必须提前知道的限制conda 的cudatoolkit包只包含运行时库不包含nvcc编译器。装完之后你敲nvcc -V会提示找不到命令这是正常的不是装失败。如果需要编译器得去装cudatoolkit-dev或者还是回系统级装完整 Toolkit。我见过有人为了装出 nvcc折腾一下午其实一开始选错方案了。可以用这条命令确认 conda 版 CUDA 装好了conda list | grep cudatoolkit # 期望看到类似于 cudatoolkit 11.3.1 h2bc3f7f_2 conda-forge3.4 Docker把 11.3 环境封进镜像里一劳永逸如果你的机器支持容器最省心的方案其实是直接用官方镜像docker run --gpus all -it \ nvidia/cuda:11.3.1-cudnn8-devel-ubuntu20.04 \ /bin/bash这个镜像里 CUDA 11.3.1、cuDNN 8、编译工具链全都齐了进去之后只需要装 Python 和 PyTorch。三个好处很明显第一本机环境完全不受污染第二镜像 tag 明确写了版本号不会出现我以为装的是 11.3这种乌龙第三镜像可以推送到内网仓库在其他机器上一键复现。注意--gpus all这个参数需要本机装好 NVIDIA Container Toolkit否则容器里看不到显卡。做深度学习部署的同学这个是标配值得单独花时间配一次。4. PyTorch-GPU 安装conda 和 pip 的真实差异Toolkit 就位之后真正的主角上场。这一步的选择题是 conda 还是 pip而这道题的答案不是哪个更好而是取决于你的依赖链长什么样。4.1 conda 安装命令的逐字拆解-c pytorch一个字都不能省conda install pytorch1.10.1 torchvision0.11.2 torchaudio0.10.1 \ cudatoolkit11.3 -c pytorch我把这条命令拆开讲因为每一个部分都是有意义的pytorch1.10.1三个包都用精确锁定版本不用避免 conda 求解器给你换成别的版本。特别是在共享环境或者依赖已经很多的环境里求解器的自由度越大出意外的概率越高。cudatoolkit11.3显式声明要 GPU 版本。这一项是整条命令里最关键的部分。如果你漏了它conda 有可能给你装一个 CPU 版本的 pytorch而且它不会报错你会得到一个大大的False。-c pytorch指定官方 channel。这是最容易漏掉、也最容易出问题的地方。如果不加这个参数conda 会去默认源defaults 或者你配置的镜像源里找 pytorch 包而默认源里的 pytorch 包是 CPU 版本没有 CUDA 支持。装完之后torch.version.cuda打印None就是这个原因。如果你在离线环境或者网络受限conda 还有个附加选项conda install pytorch1.10.1 torchvision0.11.2 torchaudio0.10.1 \ cudatoolkit11.3 -c pytorch --offline--offline要求包已经在本地缓存里。所以离线部署的正确做法是先在一台联网的同架构机器上执行一次安装包会缓存到pkgs目录把整个pkgs目录和conda-pack打好的环境一起拷到目标机。conda 方案的优点是依赖解析能力强遇到版本冲突会给出明确提示而不是硬装缺点是求解过程慢尤其是环境里已经有几十个包的时候可能卡几分钟甚至更久。亲测经验在干净的新环境里装 pytorch成功率远高于往现有环境里加。所以第一反应应该是conda create -n torch113 python3.8开一个新环境而不是在 base 里折腾。4.2 pip 方案cu113后缀到底意味着什么pip install torch1.10.1cu113 torchvision0.11.2cu113 \ torchaudio0.10.1 -f https://download.pytorch.org/whl/cu113/torch_stable.html这里有几个知识点值得反复强调cu113是 PEP 440 里的 local version 标识。它表示这个轮子是用 CUDA 11.3 编译的同时它也起到了锁版本的作用——torch1.10.1cu113只会匹配这一个特定的构建产物绝对不会被静默替换成别的 CUDA 版本或者 CPU 版本。这就是为什么我强烈建议在主版本后面带上这个后缀。-f参数指向的是官方的 whl 索引页。因为cu113这种带 local version 的包PyPI 主站上是没有的PyPI 不允许上传带 local version 的包必须从这个索引里找。等价写法还有pip install torch1.10.1cu113 torchvision0.11.2cu113 torchaudio0.10.1 \ --extra-index-url https://download.pytorch.org/whl/cu113两种写法原理类似-f更老派但兼容性更好。实际用下来-f更稳因为它强制从指定的页面找包不容易被其他源干扰。pip 的轮子里自带 CUDA 运行时。这也是为什么一个 torch 轮子能有一两个 GB 那么大——它把libcudart、libcublas、libcudnn这些全都打包在torch/lib/目录下了。这一点造成了一个非常重要的现象即使你系统里没有装 CUDA Toolkit只要驱动够新pip 装的 PyTorch GPU 版本照样能跑。反过来也说得通装了 Toolkit 但装错了 torch 轮子照样是 CPU 版。那就出现一个问题既然轮子自带运行时为什么还要装 Toolkit回到前面说的——只有需要nvcc编译自定义算子的时候才需要。日常跑模型、做微调、跑推理pip 装完就够了。这是很多人绕不过来的弯。4.3 镜像源、离线包以及装成 CPU 版的完整复现过程这是本节最有价值的部分我按顺序把最常见的翻车路径走一遍。路径一用国内镜像源装 pip 包。很多同学为了下载速度配置了国内镜像源。这里的问题是镜像源只镜像 PyPI 主站的内容而 PyPI 主站上根本没有cu113这种 local version 的包。所以当你执行pip install torch1.10.1cu113时镜像源会报No matching distribution found如果你写的是不带后缀的pip install torch1.10.1那它不仅会成功还会给你装一个 CPU 版本或者完全不同 CUDA 版本的轮子。正确做法是装 PyTorch 的时候临时关掉镜像源或者显式指定官方索引pip install torch1.10.1cu113 torchvision0.11.2cu113 torchaudio0.10.1 \ -f https://download.pytorch.org/whl/cu113/torch_stable.html \ -i https://pypi.org/simple-i显式指定主站避免被本地的 pip 配置文件带偏。装完其他普通包再切回镜像源速度该快还是快。路径二Windows 上直接用pip install torch。这个坑特别隐蔽。PyPI 主站上 Windows 平台的默认 torch 轮子在很长一段时间里就是 CPU 版本。所以一个 Windows 用户敲完pip install torch看到安装成功兴冲冲跑起来发现没有 GPU——原因就在这里。Windows 用户一定要带cu113后缀并指定-f索引页不能偷懒。路径三conda 不带-c pytorch。前面已经说过默认源的 pytorch 是 CPU 版。这个错误的隐蔽之处在于conda 会一口气把 pytorch 装好import torch也正常唯一的症状就是is_available()是False。判断当前装的是哪一版最快的办法是三条命令python -c import torch; print(torch.__version__) # 输出 1.10.1cu113 → GPU 版输出 1.10.1 → 大概率 CPU 版 python -c import torch; print(torch.version.cuda) # 输出 11.3 → 对输出 None → 铁定是 CPU 版 python -m torch.utils.collect_env # 这个内置工具会把 python、torch、CUDA、cuDNN、显卡型号全打出来排查时最好用python -m torch.utils.collect_env这条我强烈建议收藏。它输出的信息比你自己一条条敲要全得多而且格式统一发给同事帮忙看的时候特别方便。4.4 三种安装方式横向对比对比项conda -c pytorchpip 官方 whl 索引只用系统 Toolkit依赖解析强会做全局求解弱基本按顺序装不涉及是否需要系统 CUDA否conda 自带运行时否轮子自带运行时是是否提供 nvcc否除非装 cudatoolkit-dev否是多环境隔离极好删环境即清理较好靠 venv差全局生效典型耗时慢网络要求高快但下载体量大取决于安装方式适合场景依赖复杂、需要精确解析环境干净、追求速度需要编译自定义算子我自己的习惯是基础镜像环境用 conda 装一次能编出可用环境就conda pack打包留存日常迭代用 pip 在 venv 里快速试。两种都掌握遇到什么机器都不慌。5. 验证环节一句 is_available 远远不够torch.cuda.is_available()返回True只证明 PyTorch 找到了显卡完全不证明它能正常算。真正靠谱的验证要分四层一层层往下走。5.1 四层验证脚本import torch # 第一层基础可用性 print(CUDA available:, torch.cuda.is_available()) print(CUDA version:, torch.version.cuda) print(cuDNN version:, torch.backends.cudnn.version()) print(Device count:, torch.cuda.device_count()) print(Device name:, torch.cuda.get_device_name(0)) print(Capability:, torch.cuda.get_device_capability(0)) # 第二层真正的张量搬运 x torch.randn(1024, 1024, devicecuda) print(Tensor device:, x.device) # 第三层实打实做一次矩阵乘法 y torch.randn(1024, 1024, devicecuda) z torch.mm(x, y) torch.cuda.synchronize() # 关键异步操作必须同步才能捕捉错误 print(Matmul result mean:, z.mean().item()) # 第四层显存分配的边界测试 print(Allocated:, torch.cuda.memory_allocated() / 1024**2, MB) print(Reserved:, torch.cuda.memory_reserved() / 1024**2, MB)为什么要做到第三层因为CUDA 的很多错误是异步抛出的。只算不synchronize()错误会被吞掉等到后面某个不相关的地方才炸出来误导排查方向。加一个torch.cuda.synchronize()错误会在出问题的那一行立刻爆出来定位成本低一个量级。第四层的意义在于验证显存管理正常工作。如果memory_allocated一直是 0说明前面某一步其实没真正用上 GPU。同时开一个终端盯着watch -n 1 nvidia-smi跑矩阵乘法的那一瞬间你应该能看到显存占用跳上去、GPU 利用率冲到接近 100%然后落回来。如果利用率毫无波动就算is_available()是 True也说明计算没有真的落到卡上。5.2 is_available 返回 False 的排查链路按这个顺序往下走基本能在五分钟内定位问题第一步确认装的到底是哪一版 torch。python -c import torch; print(torch.__version__, torch.version.cuda)如果torch.version.cuda是None问题就找到了——装的是 CPU 版回到第 4 节重装。如果打印的是11.3说明轮子是对的继续往下。第二步确认驱动在不在、版本够不够。nvidia-smi如果这条命令本身就报命令未找到那是驱动没装跟 PyTorch 无关。如果驱动版本低于 450那 CUDA 11.x 整套都跑不起来需要先处理驱动。第三步确认是不是环境的锅。which python python -c import sys; print(sys.executable)这一步特别容易被忽略。很多明明装好了却不行的案例其实是命令行里激活的是 A 环境跑脚本时 IDE 用的是 B 环境的解释器。尤其是用 PyCharm 或者 VSCode 的时候编辑器有自己的解释器设置跟终端里conda activate出来的环境是两回事。确认两边路径一致这一步能解决相当一部分玄学问题。第四步检查动态库路径有没有被污染。echo $LD_LIBRARY_PATH ldd $(python -c import torch, os; print(os.path.join(os.path.dirname(torch.__file__),lib,libtorch_cuda.so))) | grep not found如果LD_LIBRARY_PATH里被人手工塞了/usr/local/cuda-10.2/lib64这种旧路径会出现libcudart.so.10.2: cannot open shared object之类的报错。做法是清掉环境变量里跟 CUDA 相关的旧路径只保留必要项重新打开终端再试。第五步算力是否被支持。python -c import torch; print(torch.cuda.get_arch_list())这条命令会打印当前轮子支持的算力代号列表。如果你的显卡算力不在这个列表里典型的是很老的 Kepler 卡那就是轮子本身不支持只能换更老的 PyTorch 版本或者换卡。5.3 用一次小规模真实训练做最终验收验证脚本通过之后我建议再跑一次小规模真实训练收尾。不用很大随便找个经典小模型跑几个 epoch观察这几件事训练日志里显示的 device 是不是cuda每个 iteration 的耗时是否明显低于 CPU 版本nvidia-smi里显存占用是否稳定在一个合理区间不持续上涨说明没有明显泄漏有没有出现CUDA out of memory如果有说明 batch size 或者模型规模需要调这是正常现象不是环境问题这一步做完环境才算真正可用。只看is_available()就宣布成功是一个非常常见的过度乐观。6. 装完之后的高频翻车点DLL、numpy、多版本共存与假故障环境装完的那一刻不是终点而是各种隐藏问题的起点。下面这几类问题我几乎每次带新人都要讲一遍。6.1 Windows 上的 DLL load failedWindows 用户最常遇到这个OSError: [WinError 126] 找不到指定的模块。Error loading ...\torch\lib\cudnn_ops_infer64_8.dll or one of its dependencies.看起来像是 CUDA 没装好实际上九成以上是缺Microsoft Visual C 可再发行组件。torch 的 GPU 轮子在 Windows 上依赖 VC 2015-2022 的运行库新装的系统上经常没有。去微软官网下载最新的vc_redist.x64.exe装上重启命令行问题通常就解决了。另外还有两个次要原因一是显卡驱动版本太老缺少轮子里需要的 CUDA 用户态 DLL升级驱动即可二是多个 Python 环境混装导致torch/lib下文件不完整最干净的做法是删掉环境重装。一个实用建议Windows 上装 PyTorch尽量用 conda 环境而不是全局 Python。因为 conda 环境里的 DLL 搜索路径是隔离的不容易受系统里其他软件干扰。全局环境里装过各种东西DLL 冲突的概率大幅上升。6.2 numpy 2.x 与旧版 torch 的兼容冲突这是一个近两年高发的坑。numpy 2.0 之后做了 ABI 调整和老版本编译的扩展模块不兼容。如果你用 torch 1.10 这类老版本同时系统里 numpy 被升级到了 2.ximport torch可能直接报A module that was compiled using NumPy 1.x cannot be run in NumPy 2.x解决办法很直接pip install numpy2这里有个非常反直觉的经验装 PyTorch 的时候最好让 pip 自己解析 numpy 依赖不要手动去pip install numpy升级。手动升级 numpy 是破坏老环境最快的方式之一。如果确实需要新版 numpy那就要把 PyTorch 一起升级到支持 numpy 2 的版本两者必须同步。同样的逻辑也适用于typing_extensions、pillow这些基础依赖。老环境一旦跑通非必要不升级任何基础包。我见过太多我就升了个 numpy 结果整个环境废了的案例。6.3 多版本 CUDA 共存与 LD_LIBRARY_PATH 的污染问题服务器上同时存在多个 CUDA 版本是常态处理原则是版本靠目录区分切换靠软链接绝对不要把库路径往全局环境变量里塞。ls -d /usr/local/cuda-* # /usr/local/cuda-10.2 /usr/local/cuda-11.3 /usr/local/cuda-11.8 # 切换默认版本只动软链接不动目录 sudo rm -f /usr/local/cuda sudo ln -s /usr/local/cuda-11.3 /usr/local/cuda # 确认 nvcc -V # 应该显示 release 11.3用update-alternatives管理会更规范切换也更快sudo update-alternatives --install /usr/local/cuda cuda /usr/local/cuda-11.3 113 sudo update-alternatives --install /usr/local/cuda cuda /usr/local/cuda-11.8 118 sudo update-alternatives --config cuda至于环境变量我建议不要写进/etc/profile全局生效而是写进具体项目用的激活脚本里或者在需要编译时才临时exportexport CUDA_HOME/usr/local/cuda-11.3 export PATH$CUDA_HOME/bin:$PATH export LD_LIBRARY_PATH$CUDA_HOME/lib64:$LD_LIBRARY_PATH原因是全局的LD_LIBRARY_PATH会影响机器上所有程序包括不用 CUDA 的那些。我曾遇到过因为全局设了 CUDA 库路径导致系统里另一个依赖不同版本 libstdc 的服务起不来的情况。环境变量这东西作用域越小越安全。还有一点值得强调pip 装的 PyTorch 自带 CUDA 运行时正常情况下完全不需要设置LD_LIBRARY_PATH。很多教程让你配置这个变量其实是多余的反而容易制造问题。只在编译自定义算子的场景下才需要而且应该限定在那个编译过程里。6.4 显存没占满但很卡这类假故障怎么定位最后聊一个经常被误判成环境没装好的现象nvidia-smi里显存占用不高、CPU 和内存占用也不高但训练就是慢得离谱。这种情况绝大多数不是 CUDA 装错了而是下面几类原因数据加载是瓶颈。DataLoader的num_workers设成 0所有预处理都在主线程里同步做GPU 大部分时间在等数据。把num_workers调到 4 到 8视 CPU 核数并打开pin_memoryTrue速度经常能翻倍。同步点太多。代码里频繁.item()、.cpu()、print(loss)这类操作每一次都会强制 CPU 和 GPU 同步把流水线的并行度全部打断。训练循环里尽量少做这类操作需要记录指标就在累积几步之后统一记录。计算和传输的比例失衡。模型太小、batch 太小的时候PCIe 传输的时间可能比计算时间还长GPU 利用率上不去。增大 batch size 或者换成更大的模型利用率自然会上去。共享显存被占用。在 Windows 上如果显存不够系统会把一部分内存当成共享显存来用性能和真显存差一个数量级。用nvidia-smi看一下总显存和实际可用显存是否对得上。至于容器环境里偶尔冒出来的unable to determine gpu memory usage这类告警多半是容器内没有正确挂载显卡设备或者权限不足导致的检查启动参数里有没有--gpus all以及 NVIDIA Container Toolkit 是否正常即可跟 CUDA 版本本身没关系。再补一个限制场景下的技巧如果目标机器完全离线最稳妥的搬运方式是在联网机器上用 pip 把轮子和依赖全部下载下来pip download torch1.10.1cu113 torchvision0.11.2cu113 \ -f https://download.pytorch.org/whl/cu113/torch_stable.html \ -d ./whl_packages # 拷贝到目标机器后 pip install --no-index --find-links./whl_packages \ torch1.10.1cu113 torchvision0.11.2cu113一定要用pip download而不是手动去网页上点几个文件——它会自动把依赖树一起拉齐包括 numpy、pillow、typing_extensions 这些不起眼但缺了就报错的包。我最早做离线部署的时候就是手动下了三个主包到目标机上装完缺依赖来回拷了三趟才搞全白折腾半天。如果要连环境一起搬用conda pack更彻底conda pack -n torch113 -o torch113.tar.gz # 目标机解压到指定目录后 source ./torch113/bin/activate这个方式把整个环境包括 Python 解释器、所有包、甚至 pip 缓存都打包了跨机器复现一致性最好。唯一需要注意的是打包机和目标机的系统架构要一致32 位到 64 位、x86 到 ARM 之间是不能通用的。我个人在实际操作中的体会是环境搭建这件事八成的痛苦都来自跳步。跳过体检直接装、跳过版本对照随便选、跳过四层验证看个True就收工后面迟早会以某种更难排查的形式还回来。把版本地图画清楚、把每个参数为什么这么写搞明白、把验证做到矩阵乘法这一层剩下的就只是时间问题。
返回列表