ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

PyTorch离线安装完全指南:从依赖链到GPU验证的实战流程

PyTorch离线安装完全指南:从依赖链到GPU验证的实战流程 做离线部署的工程师对一件事应该都深有体会在外网机器上pip install torch一分钟解决问题到了内网环境光是 PyTorch 离线版本安装就能折腾大半天。我日常工作经常涉及物理隔离环境这几年光是 PyTorch、TensorFlow 这类深度学习框架的离线包就攒了满满一个移动硬盘踩过的坑比教程里的步骤还多。这篇博文要解决的问题很明确在一台完全不能访问外网的机器上把 PyTorch 框架连同配套的 torchvision、torchaudio、基础依赖一起装好并且保证 GPU 能用。内容按版本选型、离线包准备、conda 环境搭建、安装验证、问题排查这条线走所有命令和步骤都在真实离线环境里验证过拿过去照着做就能复现。1. 离线安装的核心思路先搞明白依赖链再动手1.1 一条完整的离线依赖链不只是 torch 一个包很多初学者以为离线安装 PyTorch 就是“下载一个 torch.whl 文件拷过去装上”这个想法坑了不知道多少人。实测下来 torch 主包确实只是一个 wheel 文件但它在import的时候会依赖 numpy、typing-extensions、filelock、jinja2、networkx、sympy、future、pillow 等一堆包。这些依赖如果机器上没有安装 torch 之后再 import 就会直接报ModuleNotFoundError然后你开始怀疑是不是 torch 包坏了其实只是少了某个不起眼的依赖。完整的离线依赖链分四层基础层Python 解释器版本3.8、3.9、3.10、3.11、3.12 等和 pip 工具本身中间层PyTorch 主包依赖的通用 Python 库numpy、pillow、requests、typing-extensions 这些核心层torch、torchvision、torchaudio 三个 wheel 包版本必须互相配套硬件层NVIDIA GPU 驱动、CUDA 运行时、cuDNN这部分决定 GPU 能不能真正用起来。这里有一个关键知识点PyTorch 官方发布的 GPU 版 wheel 内部已经打包了运行时需要的 CUDA 动态库所以目标机器上没有安装 CUDA Toolkit 也能跑 GPU 计算只要 NVIDIA 驱动版本足够新。很多人以为必须装 CUDA Toolkit实际上不是必须的。这条经验我在多台刚装好驱动、没有任何 CUDA 开发环境的机器上验证过。1.2 版本兼容的逻辑驱动定上限wheel 定下限PyTorch 离线安装最大的坑不是“找不到安装文件”而是版本组合不兼容。举个实际例子某台机器驱动是 CUDA 11.8 驱动你下载了 cu121 的 wheel 也能装但运行时可能报CUDA driver version is insufficient反过来驱动很新却下载了旧版 torch又可能遇到某个算子缺失。所以版本选型本质上是“驱动支持版本、PyTorch 构建时用的 CUDA 版本、Python 版本、torch/torchvision/torchaudio 配套版本”四个因素一起对齐。我一般把兼容性分成三层来判断驱动决定上限。GPU 驱动能支持的最高 CUDA 版本不能低于 wheel 对应版本。比如nvidia-smi显示 CUDA Version 12.1就可以跑 cu118、cu121 的 wheel如果驱动只到 11.8那 cu121 的 wheel 即便装上也会在运行时报错。wheel 内置运行库决定实际行为。cu118、cu121 这些标签代表 PyTorch 构建时链接的 CUDA 版本不代表机器上必须安装对应版本的 CUDA Toolkit核心是驱动能否兼容。Python 与 torch 版本要一起看。新版 PyTorch 逐渐放弃 Python 3.8老版 torch 又不支持 Python 3.12装之前先查官方版本矩阵别凭印象选。这里必须多说一句torch、torchvision、torchaudio 三者是有严格配套关系的。PyTorch 2.3.1 对应 torchvision 0.18.1 和 torchaudio 2.3.1混搭很容易出幺蛾子。离线环境下 pip 默认安装最新版但你的离线目录里可能只缺某一个所以要显式指定版本号安装。1.3 一大半失败原因不是缺包是环境上下文脏我后来总结出一个规律离线环境里安装失败至少一半不是 torch 本身出了问题而是“环境上下文不一致”。比如 base 环境里装过 TensorFlowTensorFlow 可能把 numpy 锁到 2.x而 PyTorch 某些版本和 numpy 2.x 有兼容问题再比如系统里有两个 Pythonpip对应的是 3.7你下载了一个 cp310 的 wheel一装就报not a supported wheel on this platform。这些报错单独看会觉得莫名其妙实际原因就是环境太杂。离线安装的操作原则应该是一条用 conda 创建一个全新的空白环境把和业务无关的包全隔离在外面。干净的环境会让很多玄学报错直接消失。这个原则不是我个人偏好而是大量实操验证过的结论。2. 动手前的版本选型驱动、CUDA、Python 一个都不能错2.1 第一步先查 nvidia-smi读懂驱动与 CUDA 的关系拿到目标机器后第一件事不是下载安装包而是先在机器上查驱动情况。打开终端输入nvidia-smi看到右上角CUDA Version: 12.1时要特别注意这个值表示当前驱动最高支持到 CUDA 12.1并不是说机器上装了 CUDA 12.1 工具包。PyTorch 的兼容逻辑是驱动支持的最高 CUDA 版本大于等于 wheel 的 cu 标签就能正常工作。所以驱动显示 12.1你可以放心选择 cu118、cu121 的 wheel甚至 cu123/cu124 也可以前提是驱动版本足够新。如果机器上连nvidia-smi都没有说明驱动没装好或者 GPU 没有被系统识别。这种情况下哪怕 torch 装得再顺利torch.cuda.is_available()也只会返回 False。可以用命令先检查硬件lspci | grep -i nvidia有输出但nvidia-smi报错多半是驱动内核模块和当前内核版本不匹配需要先解决驱动问题再回来弄 PyTorch。这个问题在离线环境里比想象中常见很多人把安装包折腾一通发现 GPU 用不了回头一查才发现是驱动层的老大难。还有一个分支容易被忽略机器如果没有 NVIDIA GPU或者只是内网测试服务器那就老老实实选 CPU 版本。CPU 版 torch 体积小、没有 CUDA 依赖、安装简单跑跑小模型、验证代码逻辑完全够用。不要一上来就追求 GPU 版。2.2 看懂 wheel 文件名cp310、cu121、linux_x86_64 都是什么意思wheel 文件名里全是关键信息拿一个标准命名举例torch-2.3.1cu121-cp310-cp310-linux_x86_64.whl拆开来看2.3.1cu121PyTorch 版本号加 CUDA 构建标签cu121 表示用 CUDA 12.1 构建cp310适配 CPython 3.10注意只适配 3.10 这一代不向下兼容 cp39也不向上兼容 cp311linux_x86_64面向 Linux 64 位系统Windows 平台的文件名里是win_amd64。如果文件名的 cp 标签和目标 Python 版本对不上pip 会直接拒绝安装。所以下载前必须先确认 Python 版本python --version这里有一个容易被忽视的细节conda 创建环境时指定python3.10实际解释器可能是 3.10.x只要主版本一致就能用 cp310 的包但如果你用系统自带的 Python 3.9下载了 cp310 的 wheel那必然失败。Windows 用户还要注意别下载到linux_x86_64结尾的文件跨平台 wheel 不能互相安装。2.3 从官方索引下载离线包并核对校验值PyTorch 的离线 wheel 文件我不建议去第三方博客或者网盘下载。原因有两个一是第三方包的安全性没法保证二是很多包的版本标签被改过装的时候才发现对不上。最稳妥的方式是在联网机器上从 PyTorch 官方索引下载。官方 wheel 索引页面是https://download.pytorch.org/whl/torch_stable.html可以看到所有版本列表。如果要按条件下载用 pip 会更方便下面这个命令直接把 torch、torchvision、torchaudio 对应 CUDA 12.1 的包下载到本地目录pip download torch torchvision torchaudio \ --index-url https://download.pytorch.org/whl/cu121 \ --platform linux_x86_64 \ --python-version 3.10 \ --only-binary:all: \ --no-deps \ -d ./offline_packages这里注意两点指定了--platform和--python-version时一定要加--only-binary:all:否则 pip 可能会去下载源码包而不是编译好的 wheel加--no-deps是因为依赖我们会在下一步单独处理避免一次拉取时遗漏。下载完成之后建议核对一下文件的 SHA256 校验值。官方页面和包的元数据里都能查到哈希值离线环境下包一旦被 U 盘拷贝破坏想在现场排查会非常折磨。花一分钟核对后面省一小时。3. 实操全过程Anaconda 环境加离线包安装3.1 创建干净的 conda 环境别在 base 里直接装前面的理论铺垫完了现在进入真正动手阶段。以 Linux 环境为例先创建一个 Python 3.10 的独立环境conda create -n torch_offline python3.10 -y conda activate torch_offline这里要提前确认一个前提内网机器上 conda 创建环境时能否联网。如果内网有 conda 镜像源或者本地包缓存直接执行没问题如果完全离线conda create可能会卡在下载 python 包这一步。这种情况下的解决思路是在外网机器上用 conda 提前打包好一个带 Python 3.10 的环境包拷贝进去后通过conda create --offline或者直接从已有基础环境 clone。具体打包方法这里不展开但你得心里有数离线环境里最难的不是 torch 本身而是 Python 解释器怎么准备好。环境建好后检查 pip 版本。conda 环境自带 pip但版本可能偏老。离线情况下pip install --upgrade pip是执行不了的所以要么在联网机器提前下载对应 pip 的 wheel要么直接用自带版本。我实测大部分场景自带的 pip 够用真正缺的是包不是 pip。还有一点务必记住不要在 base 环境里直接装 torch。base 里往往堆了很多其他项目的东西依赖冲突的概率极高。单独建环境单独记依赖清单出了问题可以直接删掉重来成本最低。3.2 用 pip download 准备全部依赖一条命令装完在联网机器上把 torch、torchvision、torchaudio 以及它们的全部依赖都拉下来。这次不加--no-deps让 pip 自动解析依赖pip download torch torchvision torchaudio \ --index-url https://download.pytorch.org/whl/cu121 \ -d ./offline_packages执行完看一下目录内容重点确认三件事目录里除了三个主包是否还有 numpy、pillow、typing-extensions、jinja2、networkx、sympy、filelock 这些常见的依赖是否包含了 torchvision 和 torchaudio因为这两个包经常因为依赖较多被漏掉文件里是否出现了多个版本的同一个包比如 numpy 1.x 和 numpy 2.x 同时存在最好手动清理多余版本避免 pip 选错。整个目录拷贝到内网机器之后在目标机器的 conda 环境里安装pip install --no-index --find-links./offline_packages torch torchvision torchaudio建议把版本写全避免 pip 在本地目录里选到不匹配的版本pip install --no-index --find-links./offline_packages torch2.3.1 torchvision0.18.1 torchaudio2.3.1--no-index的意思是让 pip 不要联网去 PyPI 上找--find-links是告诉它只在本地目录里找。这两条参数是离线安装的标准组合。如果安装过程中提示缺某个依赖回联网机器上补充下载那个包就行不用把全部包重新拉一遍。这里要单独提醒安装时不要再带--index-url参数否则在有网的机器上 pip 会走联网路径在没网的机器上它会尝试连接然后超时白白浪费时间。3.3 安装后的核验从 import 到 GPU 计算一次走通装完先别急着跑模型老老实实跑一遍最小验证脚本确认环境真的能用import torch print(torch version:, torch.__version__) print(cuda available:, torch.cuda.is_available()) if torch.cuda.is_available(): print(device name:, torch.cuda.get_device_name(0)) x torch.randn(3, 3).cuda() print(x.sum())判断标准有三个层级。第一torch.cuda.is_available()返回 True说明 CUDA 链路已经通了第二能正常打印出设备名称说明 torch 能识别到具体显卡第三tensor.cuda()能执行计算并返回结果说明显存分配和内核编译没问题。这一步通过以后建议再跑一个真实模型片段做最终验收。我自己的习惯是在离线环境里跑一个小型 LSTM 或者强化学习算法的训练步几分钟内如果没有算子缺失、显存溢出、数值异常这套环境基本就可以交付了。做纯视觉任务的话跑一次 ResNet 的前向也能达到同样效果。只验证import torch是远远不够的因为很多算子在第一次调用时才会触发底层 CUDA 内核加载问题隐藏得很深。3.4 没有 NVIDIA GPU 怎么办CPU、AMD、国产卡分支不是所有离线机器都是 NVIDIA 环境。很多项目里机器可能是纯 CPU、AMD 显卡或者是国产 GPU它们的安装路径完全不同。纯 CPU下载 CPU 版 wheel文件名类似torch-2.3.1cpu-cp310-cp310-linux_x86_64.whl下载时把--index-url后面改成https://download.pytorch.org/whl/cpu。装完torch.cuda.is_available()永远是 False但 PyTorch 的 CPU 实现也能跑不少模型训练小网络做验证没有问题。AMD GPUPyTorch 官方提供 ROCm 版本下载地址路径类似https://download.pytorch.org/whl/rocm5.6前提是机器上 AMD 驱动和 ROCm 软件栈都正常。ROCm 的安装比 CUDA 更依赖系统环境离线部署前务必确认厂商给的安装文档。国产 GPU部分国产芯片厂商会提供自行适配的 PyTorch 分发包安装前要仔细确认厂商适配的 torch 版本、底层兼容层以及对应操作系统版本不能直接套用 NVIDIA 的 cu 系列 wheel。这类环境如果拿不准先找设备厂商要适配手册再动手。我见过太多人在国产卡上直接装官方 GPU 包装完后算子全部报不支持白折腾好几天。GPU 底层架构不一样软件栈是不可能通用的。4. 高频问题排查与最小验证4.1 离线安装报错速查表把离线安装里遇到频率最高的报错整理成一张速查表现场排查时可以对照着看报错或现象大概率原因处理方式ModuleNotFoundError: No module named numpy依赖包没有离线下载完整联网机器补充下载 numpy 等依赖重新安装torch ... is not a supported wheel on this platformwheel 的 cp 标签和 Python 版本不匹配确认解释器版本下载对应 cp 标签的包CUDA error: no kernel image is available for execution on the device驱动或 GPU 架构太老CUDA 版本过高检查nvidia-smi最高 CUDA 版本降低到 cu118 或更旧版本torch.cuda.is_available()返回 False但 torch 能 importGPU 驱动未识别或版本过低修复驱动nvidia-smi正常后再验证ImportError: libcuda.so.1: cannot open shared object file系统缺少 CUDA 动态库或驱动未装好确认驱动完整必要时配置 LD_LIBRARY_PATHtorchvision 装完报 PIL 版本冲突依赖版本被其他环境改动在全新 conda 环境重装不要混用这张表看起来简单但每一条背后都有过真实案例。尤其是no kernel image is available这条几乎每个用老显卡机器的同事都会遇到根因大多是驱动太旧或者 GPU 计算能力太低新版 PyTorch 不再生成对应架构的内核。4.2 三个容易被忽略的坑第一个坑是高版本 numpy 带来的静态冲突。PyTorch 2.x 对 numpy 2.x 支持得不好而新环境里 pip 解析依赖时很可能会拉到 numpy 2.x。如果 import 时报_ARRAY_API not found或者数值结果莫名其妙不对先去查 numpy 版本。稳妥做法是在下载依赖时显式规定 numpy 的版本范围或者安装后主动锁版本。第二个坑是 pip 和 python 不对应。很多 Linux 发行版自带 Python 3.6你又在 conda 里装了 3.10但终端敲pip时调用的可能是系统旧的 pip装出来的包全跑到旧的 site-packages 里。遇到这个问题统一用python -m pip ...形式而不是裸pip命令能避免绝大多数环境污染。第三个坑在 Windows WSL 场景。WSL2 里要用 GPUWindows 侧需要安装对应版本的显卡驱动而 WSL 内部一般不需要再装驱动直接安装 PyTorch 的 cu 版本即可。如果发现torch.cuda.is_available()为 False先确认 Windows 侧驱动版本再检查 WSL 的版本是否够新。很多人在 WSL 里折腾半天 PyTorch最后发现是 Windows 驱动几个月没更新。4.3 最小验证脚本一条命令判断环境可用把下面这段保存为check_torch_env.pyimport torch print(torch version:, torch.__version__) print(built cuda version:, torch.version.cuda) print(cudnn version:, torch.backends.cudnn.version()) print(cuda available:, torch.cuda.is_available()) if torch.cuda.is_available(): print(device name:, torch.cuda.get_device_name(0)) props torch.cuda.get_device_properties(0) print(device capability:, props.major, props.minor) print(device memory:, props.total_memory // (1024 ** 2), MB)执行python check_torch_env.py返回的每一项都有意义。built cuda version告诉你当前 torch 是用哪个 CUDA 版本编译的cudnn version确认 cuDNN 是否正常device capability对应 GPU 的计算能力比如 8.6 是 RTX 3090/4090 的安培架构对比官方支持列表可以判断是否该换旧版 torch。跑通这个脚本后再用一个带循环的小模型做 forward 几十步计算确认 loss 有变化就可以认为环境验收完成。这个流程任何人过来问我都是这么教的稳定可靠。5. 离线部署流程中的几点实在体会5.1 维护一个自己的离线包仓库离线部署不是一次性工作。项目多了以后不同机器可能需要不同版本的 PyTorch所以离线包的管理习惯很重要。我的做法是在本地按目录分类torch/2.3.1/cu121/、torch/2.3.1/cpu/、torch/1.13.1/cu117/这样建立层级每个目录里放一个requirements.txt和README记录下载命令、校验值、适用范围。半年后自己再来找包不用重新查资料效率高很多。5.2 现场部署前先在联网机器上完整跑一遍这条建议听起来基础但真的能救命。第一次离线装某个版本前在联网机器上用一个全新 conda 环境按完整流程装一遍记录下所有依赖和坑再整理成离线安装包。这样到现场操作时每一步都有底不会临时发现缺包。我在一个海光 GPU 的项目里就是这么做的把厂商适配包和官方依赖在测试机上跑通后再入场现场两个小时就完成了部署。5.3 版本锁定与交付记录交付离线环境时我会输出一份版本清单包含 Python 版本、pip 版本、torch/torchvision/torchaudio 版本、CUDA 构建版本、驱动版本、依赖包版本。这份记录既方便后续维护也能在别人报环境问题时快速定位是哪个环节不一致。命令很简单pip freeze requirements.txt但很多人就是懒得做。真出了问题再回头反查代价要高得多。最后再分享一个我自己的习惯所有离线安装包传完后第一时间在目标机器上执行一次最小验证脚本确认能跑再让使用方接手。这一步多花五分钟能省掉后面无数个“为什么我的环境跑不起来”的深夜排查。
返回列表