ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

PyTorch在Windows报shm.dll加载失败?从依赖链定位VC++运行库缺失

PyTorch在Windows报shm.dll加载失败?从依赖链定位VC++运行库缺失 1. 问题现场还原与核心症结定位1.1 报错长什么样从一行红字说起如果你在 Windows 上装完 PyTorch 2.3.0兴冲冲打开终端敲下import torch结果迎面而来的是一屏红色堆栈最后一行写着OSError: [WinError 126] 找不到指定的模块。Error loading D:\...\torch\lib\shm.dll or one of its dependencies.——恭喜你你撞上了 PyTorch 在 Windows 平台上最经典、也最容易被误诊的一类问题。这个报错有个非常迷惑人的地方它明确告诉你shm.dll加载失败于是绝大多数人的第一反应是“shm.dll 这个文件是不是丢了是不是被杀毒软件删了是不是下载不完整”然后开始疯狂重装、换源、换版本折腾一整天问题依旧。我见过太多人在群里贴出这个报错然后下面一堆人回复“重装吧”“换 conda 装”“用 pip 装”结果没有一个真正解决问题。真相是shm.dll本身大概率好好地躺在torch\lib目录里它没丢也没坏。真正的问题在于——它依赖的某个更底层的 DLL 找不到。Windows 的 DLL 加载机制是“链式”的当你加载 A.dll 时系统会去解析 A 的导入表把它依赖的 B、C、D 全部找出来加载。只要链条上任何一环断了系统报的错永远是“A 加载失败”而不会告诉你“其实是 B 找不到”。这就是为什么报错信息会“甩锅”给shm.dll。1.2 为什么偏偏是 shm.dll 背锅要理解这一点得先知道shm.dll在 PyTorch 里是干什么的。shm是 shared memory共享内存的缩写这个模块负责 PyTorch 在多进程场景下的共享内存管理比如DataLoader开多个 worker 进程时张量数据就是通过共享内存来传递的避免每个进程都复制一份数据。它属于 PyTorch 比较底层的基础设施模块。关键在于shm.dll依赖了相当多的系统级运行库尤其是Microsoft Visual C Redistributable系列简称 VC 运行库以及 Windows 自带的一些系统 DLL。当这些依赖缺失或版本不对时shm.dll就成了第一个“倒下”的多米诺骨牌因为它在torch包初始化的早期就被加载了。所以看到shm.dll加载失败你的排查方向不应该是“shm.dll 怎么了”而应该是“shm.dll 依赖的东西怎么了”。这个思维转变是解决这类问题的分水岭。1.3 这个问题到底影响哪些人从实际反馈来看这个问题高度集中在以下几类场景Windows 10/11 上全新搭建 PyTorch 环境的新手尤其是用 pip 直接pip install torch装完就报错的用 Anaconda 创建了干净虚拟环境但系统层面缺少 VC 运行库的用户从 CPU 版本切换到 GPU 版本或者从旧版本升级到 2.3.0 之后突然报错的在服务器或公司电脑上系统被精简过、运行库被裁剪过的环境。而 macOS 和 Linux 用户基本不会遇到这个问题因为这两个系统的动态库加载机制和依赖管理方式与 Windows 完全不同。这也是为什么你在网上搜解决方案时会看到大量 Linux 下的答案对你毫无帮助。提示如果你在 Linux 上遇到类似的libxxx.so找不到的问题排查思路类似但具体手段不同本文聚焦 Windows 平台Linux 的排查我会在最后一节简单带过。2. 依赖链条拆解shm.dll 到底依赖了什么2.1 用工具看清依赖关系光靠猜是没用的得用工具把shm.dll的依赖关系扒出来。Windows 上最趁手的工具是Dependencies原 Dependency Walker 的现代替代品开源免费或者微软自家的dumpbin随 Visual Studio 一起安装。用 Dependencies 打开你的环境路径\Lib\site-packages\torch\lib\shm.dll你会看到一棵依赖树。重点看两类节点红色或黄色标记的节点表示这个 DLL 找不到或者架构不匹配系统 DLL比如KERNEL32.dll、ADVAPI32.dll这些通常在C:\Windows\System32下一般不会缺VC 运行库 DLL比如VCRUNTIME140.dll、VCRUNTIME140_1.dll、MSVCP140.dll、MSVCP140_1.dll、MSVCP140_2.dll、CONCRT140.dll等这些是重灾区。我实测下来PyTorch 2.3.0 的shm.dll依赖链里最常见的缺失项就是VCRUNTIME140_1.dll和MSVCP140_1.dll这两个。它们属于 Visual C 2015-2022 Redistributable 的一部分很多“纯净版”系统或者只装了老版本运行库的机器上就是没有。2.2 VC 运行库最容易被忽视的隐形依赖这里要展开讲一下 VC 运行库的版本问题因为它是这个报错的头号元凶。微软的 VC 运行库从 2015 版开始做了一个重大改变2015、2017、2019、2022 这四个版本共用同一套运行库文件统称为“Microsoft Visual C 2015-2022 Redistributable”。也就是说你装 2022 版的运行库就同时覆盖了 2015 到 2022 的所有需求。但问题在于这套运行库又分x8632位和x6464位两个独立安装包而且它们可以共存。很多人只装了 x86 版因为某些老软件需要却没装 x64 版而 PyTorch 是 64 位的它需要的是 x64 版的运行库。反过来也一样只装 x64 不装 x86某些 32 位工具又会出问题。更隐蔽的是即使你装了运行库如果版本太老比如只装了 2015 初版缺少VCRUNTIME140_1.dll这个较新才加入的文件照样会报错。VCRUNTIME140_1.dll是随 VS2019 引入的专门用于处理 C 异常的一些底层机制PyTorch 2.x 编译时用到了它。2.3 系统 PATH 与 DLL 搜索顺序的坑除了运行库缺失另一个高频原因是DLL 搜索路径问题。Windows 加载一个 DLL 时会按照一个固定的顺序去搜索应用程序所在目录系统目录C:\Windows\System3216 位系统目录Windows 目录当前工作目录PATH 环境变量中列出的目录。注意第 5 条——当前工作目录。这意味着如果你在某个目录下运行 Python而这个目录里恰好有一个同名但版本不对的 DLL它会被优先加载导致冲突。这种情况在项目目录里混放了各种库文件时特别常见。还有一个经典陷阱Anaconda 的Library\bin目录没有加入 PATH。用 conda 安装 PyTorch 时很多依赖库比如 MKL、OpenMP 相关的 DLL会被放在Anaconda安装目录\Library\bin下。如果这个目录不在 PATH 里PyTorch 加载时就找不到这些依赖。这是 conda 环境特有的坑pip 安装一般不会遇到。2.4 架构不匹配32 位与 64 位的错配还有一种情况是架构错配。比如你的 Python 是 64 位的但 PATH 里某个目录下有一个 32 位的同名 DLL系统尝试加载时就会失败。或者反过来你装的是 32 位 Python却去加载 64 位的 PyTorch。判断方法很简单在 Python 里执行import platform; print(platform.architecture())看输出是(64bit, ...)还是(32bit, ...)。PyTorch 2.x 官方只提供 64 位版本所以你的 Python 必须是 64 位的。3. 系统化排查流程从现象到根因3.1 第一步确认 Python 与 PyTorch 架构一致排查任何 DLL 问题之前先把这个基础确认了否则后面全是白费功夫。import platform print(platform.architecture()) print(platform.python_version())如果输出是 32 位那基本可以确定问题所在了——卸载 32 位 Python装 64 位的。这一步能筛掉一部分“装错版本”的情况。3.2 第二步用 Dependencies 定位缺失的依赖这一步是核心。下载 Dependencies 工具GitHub 上 lucasg/Dependencies 项目用它打开shm.dll。打开后重点看左侧树状结构里有没有标红的节点。标红意味着“找不到这个文件”。把标红的文件名记下来然后去系统里搜这个文件在不在。如果标红的是VCRUNTIME140_1.dll、MSVCP140_1.dll这类那答案就明确了——装 VC 运行库。如果标红的是c10.dll、torch_cpu.dll这类 PyTorch 自己的库那可能是安装不完整需要重装 PyTorch。如果标红的是libiomp5md.dll这类那是 Intel OpenMP 运行库conda 环境下常见。3.3 第三步检查 VC 运行库安装情况打开“控制面板 → 程序和功能”搜索“Visual C”看看装了哪些版本。理想情况下你应该能看到Microsoft Visual C 2015-2022 Redistributable (x64)Microsoft Visual C 2015-2022 Redistributable (x86)如果只有 x86 没有 x64或者版本号很老比如 14.0 开头而不是 14.3x 开头那就需要更新。判断版本号的方法在“程序和功能”里看版本列14.0 是 201514.1 是 201714.2 是 201914.3 是 2022。PyTorch 2.3.0 建议至少 14.3x 版本。3.4 第四步检查 PATH 环境变量在终端里执行echo %PATH%或者用 Pythonimport os for p in os.environ[PATH].split(os.pathsep): print(p)重点确认两件事C:\Windows\System32在不在 PATH 里正常都在如果用 conda你的Anaconda目录\Library\bin在不在 PATH 里。如果Library\bin不在可以手动加上或者用 conda 的激活脚本自动处理。3.5 第五步排除当前目录的干扰在报错的目录下执行dir *.dll看看有没有和依赖同名的 DLL 文件。如果有把它们移走再试。这个坑很隐蔽因为报错信息完全不会提示你“当前目录有冲突文件”。4. 针对性修复方案与实操步骤4.1 方案一安装/修复 VC 运行库覆盖 80% 的情况这是最优先尝试的方案因为绝大多数shm.dll报错都是运行库问题。操作步骤去微软官网搜索“Microsoft Visual C Redistributable latest supported downloads”找到官方下载页下载vc_redist.x64.exe64位版PyTorch 必需和vc_redist.x86.exe32位版建议一起装先装 x64再装 x86如果已经装过选择“修复”而不是“卸载重装”修复更快且不会影响其他软件装完后重启电脑这一步很多人省略但运行库更新后不重启某些进程可能还在用旧的内存映射。重启后再import torch试试。我实测下来这一步能解决大约八成的shm.dll报错。注意不要从第三方下载站下运行库那些打包的“运行库合集”经常夹带私货或者版本混乱。认准微软官方。4.2 方案二修复 conda 环境的 PATH 配置如果你是用 conda 装的 PyTorch且方案一无效那大概率是 PATH 问题。操作步骤找到你的 Anaconda 安装目录比如D:\Anaconda3确认D:\Anaconda3\Library\bin这个目录存在且里面有libiomp5md.dll、mkl_*.dll等文件把这个目录加到系统 PATH 的最前面注意是最前面避免被其他目录的同名文件抢先重新打开终端PATH 修改后必须新开终端才生效激活你的 conda 环境再试import torch。如果不想改系统 PATH也可以在激活环境后手动设置set PATHD:\Anaconda3\Library\bin;%PATH%或者在 Python 代码里临时加import os os.add_dll_directory(rD:\Anaconda3\Library\bin) import torchos.add_dll_directory是 Python 3.8 之后推荐的 DLL 搜索路径添加方式比改 PATH 更精准只影响当前进程。4.3 方案三彻底重装 PyTorch排除安装损坏如果前两个方案都无效可能是 PyTorch 安装本身不完整。这时候需要彻底清理后重装。操作步骤# 先卸载 pip uninstall torch torchvision torchaudio -y # 清理残留conda 环境 conda clean --all -y # 删除 site-packages 下残留的 torch 目录如果有 # 手动去 Lib\site-packages 下检查 # 重新安装指定官方源 pip install torch2.3.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu如果是 GPU 版本把cpu换成对应的 CUDA 版本比如cu121。重装时建议加上--no-cache-dir避免用到损坏的缓存包pip install torch2.3.0 --no-cache-dir --index-url https://download.pytorch.org/whl/cpu4.4 方案四用 os.add_dll_directory 精准注入路径这是我最推荐的一种“优雅”方案尤其适合不想动系统 PATH 的场景。在导入 torch 之前先把所有可能需要的 DLL 目录加进去import os import sys # 你的环境路径按实际情况改 env_path rD:\Anaconda3\envs\pytorch_env dll_dirs [ os.path.join(env_path, Library, bin), os.path.join(env_path, Lib, site-packages, torch, lib), os.path.join(env_path, DLLs), ] for d in dll_dirs: if os.path.isdir(d): os.add_dll_directory(d) import torch print(torch.__version__)这段代码的好处是它只影响当前 Python 进程不会污染系统环境而且可以精确控制搜索顺序。我把它封装成一个fix_torch_import.py在需要的时候先 import 它再 import torch屡试不爽。4.5 方案五检查杀毒软件与安全策略拦截有些安全软件会拦截 DLL 的加载尤其是 PyTorch 这种会加载大量动态库的程序。表现就是文件明明在但就是加载不了。排查方法临时关闭杀毒软件的实时防护再试import torch如果关掉就好了说明是误拦截把 PyTorch 的安装目录加入白名单检查 Windows Defender 的“受控文件夹访问”是否开启它有时会阻止程序加载非系统目录的 DLL。这个坑我踩过一次折腾了半天运行库最后发现是某安全软件把torch\lib目录给“保护”起来了。5. 常见问题速查与避坑经验5.1 高频问题速查表报错特征最可能原因优先尝试方案报shm.dll加载失败系统较新VC 运行库缺失方案一装 x64 运行库conda 环境报错pip 环境正常Library\bin 不在 PATH方案二加 PATH 或 add_dll_directory重装多次仍报错安装包损坏或缓存问题方案三--no-cache-dir 重装文件存在但加载失败杀软拦截或架构不匹配方案五 检查架构报错指向 c10.dll 而非 shm.dllPyTorch 安装不完整方案三彻底重装换目录运行就正常当前目录有冲突 DLL移走当前目录的 DLL 文件5.2 我踩过的三个坑坑一以为重装能解决一切。我最早遇到这个问题时第一反应是卸载重装结果重装了三次每次都是同样的报错。后来才明白问题根本不在 PyTorch 本身而在系统运行库。重装一百次也没用。坑二忽略了 conda 和 pip 的环境差异。有一次我在 conda 环境里怎么都修不好换成 pip 装到另一个环境就正常了。原因是 conda 装的 PyTorch 依赖 conda 自己的 MKL 和 OpenMP 库这些库在Library\bin下而 pip 装的是自包含的版本。理解这个差异后排查方向就清晰了。坑三PATH 顺序问题。我把Library\bin加到了 PATH 末尾结果还是报错。后来发现 PATH 前面有个目录里有个老版本的libiomp5md.dll被优先加载了。把Library\bin挪到最前面才解决。PATH 的顺序真的很重要。5.3 一个万能的诊断脚本我把排查过程写成了一个脚本遇到类似问题直接跑一遍基本能定位到原因import os import sys import platform import glob print( * 50) print(Python 架构:, platform.architecture()) print(Python 版本:, platform.python_version()) print( * 50) # 检查 torch 是否安装 try: import torch print(torch 版本:, torch.__version__) print(torch 路径:, os.path.dirname(torch.__file__)) except Exception as e: print(torch 导入失败:, e) # 检查 VC 运行库 print(\n检查 VC 运行库:) sys32 rC:\Windows\System32 for dll in [VCRUNTIME140.dll, VCRUNTIME140_1.dll, MSVCP140.dll, MSVCP140_1.dll]: path os.path.join(sys32, dll) print(f {dll}: {存在 if os.path.exists(path) else 缺失}) # 检查 PATH 中的关键目录 print(\nPATH 中的关键目录:) for p in os.environ.get(PATH, ).split(os.pathsep): if Library in p or torch in p.lower(): print(f {p}) # 检查当前目录的 DLL print(\n当前目录的 DLL 文件:) for f in glob.glob(*.dll): print(f {f})这个脚本能一次性把架构、运行库、PATH、当前目录冲突全查一遍省得你一个个手动确认。5.4 关于 Ubuntu 等 Linux 环境的补充虽然本文聚焦 Windows但 Linux 下也有类似的libxxx.so找不到问题。排查思路类似用ldd命令查看依赖比如ldd /path/to/libtorch.so看哪个依赖标了not found。Linux 下常见的是缺libgomp.so.1或libstdc版本太老解决方式是apt install libgomp1或者升级 GCC 运行库。核心逻辑是一样的——顺着依赖链找断点。6. 预防措施与长期维护建议6.1 环境搭建时的最佳实践与其事后排查不如一开始就把环境搭对。我的建议是优先用 conda 创建独立环境不要往 base 环境里装 PyTorch避免污染装 PyTorch 之前先装 VC 运行库把它当成前置依赖用官方推荐的安装命令去 PyTorch 官网的 Get Started 页面选好配置复制命令不要自己瞎拼记录环境信息用conda env export environment.yml或pip freeze requirements.txt保存方便复现。6.2 多环境共存时的路径管理如果你机器上有多个 Python 环境base、conda env、venv 等PATH 管理就格外重要。我的做法是不把任何环境的Library\bin永久加到系统 PATH避免互相干扰用 conda 的conda activate自动管理它会临时修改 PATH在代码里用os.add_dll_directory精准注入只影响当前进程。这样每个环境互不干扰切换时也不会出现“这个环境能用那个环境不能用”的诡异现象。6.3 版本升级时的注意事项从旧版本升级到 PyTorch 2.3.0 时建议先卸载干净再装不要直接pip install --upgrade。因为新旧版本的依赖库可能不同直接升级容易留下残留文件导致冲突。升级前先备份环境配置升级后跑一遍诊断脚本确认所有依赖都正常。如果升级后报错第一时间用 Dependencies 看依赖链而不是盲目重装。6.4 团队协作时的环境统一如果是团队开发建议统一环境配置。把environment.yml或requirements.txt纳入版本控制新成员入职时按文件一键复现环境。同时把 VC 运行库的安装也写进环境搭建文档作为必装项。我见过太多团队因为环境不一致导致“在我机器上能跑”的经典问题。统一环境配置能省掉大量沟通成本。最后分享一个我个人的习惯每次在新机器上搭 PyTorch 环境我都会先跑一遍那个诊断脚本确认运行库、PATH、架构都没问题再开始装 PyTorch。这个前置检查花不了两分钟但能避免后面几个小时的折腾。踩过几次坑之后我越来越相信——排查 DLL 问题的核心不是记住某个具体命令而是建立“顺着依赖链找断点”的思维习惯。掌握了这个思路不管是shm.dll还是别的什么 DLL你都能自己定位到根因。
返回列表