Windows下MMDetection+mmcv-full从零编译实战:版本匹配与避坑指南
帮朋友排了一下午的Windows环境问题结果发现绝大多数报错都挤在同一个位置mmcv-full怎么都编译不过。机器上Python、PyTorch、CUDA都齐了一到编译就崩Cython报错、cl.exe找不到、CUDA_HOME没定义各种花样轮着来。其实只要理清版本匹配关系把编译环境准备到位MMDetection 2.19.0搭配mmcv-full 1.3.17在Windows 10上完全能跑通。这篇教程就是干这个的从一个只装了系统的Win10开始把Python虚拟环境、Visual Studio编译环境、CUDA/PyTorch、mmcv-full源码编译、MMDetection安装验证一直到跑出第一张检测结果图整条链路讲清楚。标题里说“最详细”我不打算只说步骤——每个关键步骤背后是什么原因、会卡在哪、怎么排查都会写到。不管你现在是刚接触目标检测的新手还是被报错折磨的半个老手按这个流程走基本能避掉九成已知的坑。1. 装之前先弄明白2.19.0和1.3.17为什么必须绑在一起1.1 版本匹配是第一道生死线MMDetection不是一个孤立的库它是一个搭建在mmcv之上的目标检测工具箱。真正干活的底层算子、数据增强、IOU计算、NMS这些逻辑大部分都在mmcv里实现mmdet只是把模型结构、训练流程、评测逻辑串起来。所以你只装mmdet是跑不起来的必须先有配套的mmcv。那为什么标题里固定写“MMDetection 2.19.0 mmcv-full 1.3.17”因为2.19.0这个版本在官方依赖说明里明确写了需要mmcv-full 1.3.17。注意这里是大于等于不是等于。理论上你装mmcv-full 1.4.0、1.5.0原则上也能跑但我在实际使用中遇到过一个问题更高的mmcv版本会调整部分算子接口的命名和参数顺序mmdet 2.19.0的源码未必跟得上。结果就是能import一跑训练或者推理就报TypeError或者AttributeError。所以在Windows上最稳妥的做法就是卡死在1.3.17不去追新。有人可能会问为什么不直接装最新版的mmdet和最新版的mmcvWindows不是Linux很多预编译好的二进制包在Linux上有Windows上没有。最新版往往只提供Linux下的wheel你拿过来在Windows上跑会立刻翻车。再说了目标检测算法研究用的模型结构都已经很成熟2.19.0这个版本支持常见的Faster R-CNN、Mask R-CNN、RetinaNet、Cascade R-CNN、YOLOv3这些主力模型对于绝大多数场景完全够用。先把这套稳定组合跑通再考虑升级不迟。1.2 mmcv和mmcv-full的差别很多第一次装的人会踩一个很隐蔽的坑看到有mmcv和mmcv-full两个包名顺手就pip install mmcv以为少装一个依赖更轻量。这个想法在纯CPU推理场景偶尔能跑但只要模型里用到自定义算子立刻报错。典型报错是AttributeError: module mmcv has no attribute ops或者ModuleNotFoundError: No module named mmcv.ops原因很简单mmcv是基础版只提供通用张量操作不包含编译过的扩展算子mmcv-full是完整版里面包含了ROIAlign、Deformable Convolution、NMS这类在检测模型里几乎必用的CUDA算子。训练也好推理也好都必须用mmcv-full。标题里特意强调mmcv-full最新版1.3.17就是提醒你别装错成mmcv。1.3 Windows下的版本组合参考这块我直接给出一个经过实测的参考组合照着配不会出大问题组件推荐版本备注Python3.7 或 3.83.6太老容易出现依赖兼容问题3.9以上容易出现Cython/Distutils异常PyTorch1.8.1 或 1.9.0与CUDA 10.2/11.1均能匹配不推荐直接追最新CUDA Toolkit10.2 或 11.1根据显卡驱动支持情况二选一mmcv-full1.3.17与mmdet 2.19.0官方匹配mmdet2.19.0本教程的目标版本这个组合不是随便拍的。PyTorch版本太新比如直接上2.xmmcv 1.3.17源码编译时会遇到编译接口不兼容的问题PyTorch版本太老比如1.4以下很多新算子的实现编译不过去。Python版本也是同理3.7和3.8是当时那批编译链最成熟的环境。2. 环境准备Python、Visual Studio、CUDA三件套怎么配2.1 用虚拟环境隔离别污染系统Python我建议不要在系统Python里直接装这套东西因为后面要卸载重装会非常痛苦。用Miniconda或者Anaconda创建一个独立环境是效率最高的做法。打开你的命令行终端建议直接用Anaconda Prompt执行conda create -n openmmlab python3.7 -y conda activate openmmlab环境名叫openmmlab只是我的一个习惯你改成mmdet或者det都行。激活之后后面所有操作都要在这个环境里进行。一个很常见的翻车现场是环境没激活就开始pip install最后装到了base环境排查半天还以为是版本冲突。这里为什么推荐Python 3.7而不是最新的Python因为mmcv编译依赖Cython旧版Cython在3.9以上的Python上偶尔会出现distutils相关的问题浪费时间。用3.7很多历史遗留的兼容问题根本不会遇到。我见过有人卡了一整天最后发现只是Python版本太新。2.2 Visual Studio Build Tools才是真正的门槛Windows上装mmcv-full最大的门槛不是网速不是CUDA而是Visual Studio。因为mmcv-full在Windows下没有官方编译好的whl只能从源码本地编译。本地编译C和CUDA扩展必须要MSVC编译器也就是Visual Studio的C工具链。装VS Code没用装MinGW也不一定好使最省心的就是装Visual Studio Build Tools。具体操作去Visual Studio官网下载Build Tools for Visual Studio 2019注意不是直接装Visual Studio Code那种轻量级工具。安装时勾选“使用C的桌面开发”这一项会带上MSVC编译器和Windows SDK。如果不确定可以把“用于Windows的C CMake工具”也一起勾上后面用起来更顺手。安装完最好重启一次电脑让系统环境变量彻底生效。很多报错比如error: Microsoft Visual C 14.0 is required. Get it with Build Tools for Visual Studio十有八九就是这一步没做好。编译器没有Python的setuptools根本没法编译任何C扩展。2.3 显卡驱动、CUDA和PyTorch的对应检查先打开cmd输入nvidia-smi看右上角的CUDA Version。比如显示的CUDA Version: 11.1说明当前驱动支持的最高CUDA版本是11.1那么你可以放心安装CUDA 11.1。如果驱动版本很旧支持的CUDA版本只有10.2那就老老实实装10.2不要强行上新版。这里有个容易混淆的点PyTorch默认自带了CUDA runtime所以很多教程让你装PyTorch时选cu111或者cu102。但mmcv-full编译时要用本机安装的CUDA Toolkit因为它要通过nvcc把算子源码编译成动态库。所以不要以为装了PyTorch就不用装CUDA Toolkit了两个都要有。安装完CUDA Toolkit之后确认环境变量。一般安装在C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.1。在cmd里执行set CUDA_HOMEC:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.1如果机器里装了多个CUDA版本要注意PATH环境变量里哪个CUDA路径排在前面因为编译时只会找第一个nvcc。可以通过where nvcc来确认用的是哪个版本。如果输出为空说明nvcc没加到PATH里需要手动把C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.1\bin加到PATH。然后安装与CUDA匹配的PyTorch。这里推荐pip install torch1.8.1cu111 torchvision0.9.1cu111 -f https://download.pytorch.org/whl/torch_stable.html如果用的是CUDA 10.2就把命令里的cu111换成cu102。装完之后立刻验证python -c import torch; print(torch.__version__); print(torch.cuda.is_available())必须输出True。如果输出False先不要往下走一定是你装的PyTorch和CUDA版本不匹配。这种情况下硬着头皮去编译mmcv后面大概率也会出幺蛾子。3. mmcv-full 1.3.17源码编译Windows安装最硬的一块骨头3.1 为什么不能直接pip install mmcv-full在Linux上一行pip install mmcv-full1.3.17基本就完事了因为官方和社区维护了对应的Linux wheel。但在Windows上mmcv-full很长一段时间都没有发布官方预编译包。你说我强行pip install mmcv-full1.3.17行不行行但pip会当场下载源码然后在本地执行编译。如果你没装Visual Studio环境、没装ninja、没设置好环境变量第一天全部翻车。其实它并不是不能编译而是缺少一份能按顺序执行的指南。所以最好的选择就是主动从源码编译并且把编译环境一步步配好。编译之前先做一个保险动作pip install ninja cythonninja是一个构建加速工具能极大缩短编译时间。cython是mmcv源码里的.pyx文件转成C的必备工具。漏掉任何一个后面都会报错。3.2 源码编译的完整操作步骤在终端里执行conda activate openmmlab git clone https://github.com/open-mmlab/mmcv.git cd mmcv git checkout v1.3.17注意git checkout v1.3.17是切到对应版本的tag别直接clone最新master就去编译。最新master可能已经有了很多新的接口变化和mmdet 2.19.0对不上。然后设置两个关键的编译环境变量set DISTUTILS_USE_SDK1 set MSSdk1这两个变量非常核心。DISTUTILS_USE_SDK1是告诉Python的setuptools自动去使用Visual Studio SDK环境而不是傻傻地去PATH里找cl.exe。MSSdk1同理是为了让构建系统能找到Windows SDK的路径。很多人编译失败就是漏了这两条。接着执行编译python setup.py develop如果不想用develop也可以用pip install -e .本质一样。develop模式会把mmcv以开发安装的方式链接进当前Python环境以后改mmcv源码不用重新安装调试很方便。编译过程会有大量输出持续十几分钟到半小时都是正常的。如果电脑内存不大可以把并行任务数限制一下避免直接编译到内存爆炸set MAX_JOBS4然后再执行编译命令。这个MAX_JOBS是mmcv编译脚本支持的环境变量限制同时编译的任务数实测在Windows上非常有用。3.3 高概率踩中的报错与排除方法我在Windows上编译过好几次mmcv基本把常见报错都遇了一遍。下面按出现频率排序报错信息原因解决办法error: Microsoft Visual C 14.0 is required没装VS Build Tools安装VS2019 Build Tools勾选C桌面开发然后重启终端unable to find vcvarsall.batVS环境没被正确识别重新打开Anaconda Prompt设置DISTUTILS_USE_SDK1和MSSdk1后重试CUDA_HOME is not set or cannot be found没设置CUDA路径执行set CUDA_HOME你的CUDA安装路径fatal error C1083: Cannot open include file: cuda_runtime.hCUDA Toolkit路径没生效检查PATH里的bin目录和include目录是否正确Error: Cython could not be imported没装cython先pip install cythonerror: command cl.exe failedVS编译器没调用成功重点检查MSVC是否完整别只装Windows SDK就完事内存爆掉编译中断并行任务太多set MAX_JOBS4后重新编译还有一个容易忽略的情况如果你原来安装过多个Visual Studio版本比如VS2017和VS2019共存编译时可能会错乱选择了旧版编译器。这时候最好指定环境变量set CCcl.exe或者干脆把老版本VS卸载掉只保留一个Build Tools。这样最干净。3.4 编译成功后先做两件事编译成功后先验证版本python -c import mmcv; print(mmcv.__version__)应该输出1.3.17。然后验证扩展算子是否真的编译进去了python -c from mmcv.ops import nms; print(ops ok)如果输出ops ok恭喜mmcv-full这一步才算真正成功。你也可以到mmcv安装目录看一下是否生成了类似mmcv/_ext.cp37-win_amd64.pyd的文件这个.pyd就是C扩展编译出来的产物它的存在说明算子模块可用。记住如果在import mmcv之后没有主动导入mmcv.ops很多问题会被隐藏直到你真正跑det模型时才暴露。所以这一步验证别偷懒。4. 安装MMDetection 2.19.0并跑通检测Demo4.1 安装MMDetection本体mmcv编译好之后压力瞬间小了一半。接下来安装MMDetection就轻松了。我建议用源码方式安装因为这样会附带完整的configs文件夹后续跑Demo、改参数都方便。执行git clone https://github.com/open-mmlab/mmdetection.git cd mmdetection git checkout v2.19.0然后安装依赖和本体pip install -r requirements/build.txt python setup.py developrequirements/build.txt里包含pycocotools、numpy、matplotlib这些关键依赖。如果在Windows下安装pycocotools时报编译错误可以先去装一个社区编译好的whl版本再继续。这个坑在Windows上非常常见但解决办法也成熟先单独把pycocotools通过预编译whl装上再执行pip install -r requirements/build.txt就不会再触发它的源码编译。如果你不想源码安装直接pip install mmdet2.19.0也可以但那样的话configs文件不在本地后面运行Demo还得单独去官方仓库下载多一道工序。4.2 用一行命令验证环境安装完成之后执行python -c import mmdet; print(mmdet.__version__)如果输出2.19.0说明MMDetection本体已经正确安装。这里我建议大家同时跑一下python -c import mmdet; print(mmdet.__version__); import mmcv; print(mmcv.__version__)把两个版本同时打出来一眼就能看出环境有没有串。4.3 下载配置和权重跑第一张检测图接下来就是最有成就感的环节真的跑一张图。先准备一张测试图片比如放到当前目录下叫test.jpg。然后从官方Model Zoo下载一个检测模型权重。最稳妥的是直接用Faster R-CNN系列因为它的配置文件和权重都非常成熟。假设你下载好的权重文件放在checkpoints/目录下文件名是faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth。然后在mmdetection主目录下执行python demo/image_demo.py test.jpg \ configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py \ checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth第一次运行会自动加载模型权重、跑前向推理然后终端里会打印检测到的目标框坐标和类别信息同时生成一张带标注框的结果图。如果你想指定输出文件名可以在命令后面加--out-file result.jpg如果一切顺利你会看到类似person 0.982这样的类别概率输出。到这一步整套安装就算彻底跑通。4.4 Demo阶段的常见异常这段过程也不是完全没有报错可能。我把常见的列出来现象原因处理方式报KeyError: cuda设备参数没写对检查是否加了--device cuda或者确认torch.cuda.is_available()为True显存不足图片太大或者模型太重换成小图或者加--device cpu先验证流程权重文件下载不完整网络中断或磁盘空间不足重新下载并核对官方给出的文件大小和MD5输出结果里全是低分框没下载对应config或者config和权重不匹配确保使用了faster_rcnn_r50_fpn_1x_coco.py对它配套的权重别拿其他模型的权重乱配如果在CPU上跑速度会比较慢这是正常的。但demo能跑通至少证明了mmcv-full的扩展算子没白编译。5. 这套方法怎么迁移到更新版本的mmdet5.1 最新版本的版本号查法标题最后写了“本方法可适用于最新版本mmdet”重点在于方法而不是具体版本号。以后如果出到2.25、2.26或者更高的版本安装逻辑是完全可以复用的。先去官方安装文档查看“Installation”章节那里会写清楚当前版本对应的mmcv-full最低版本号。这个数字是你唯一需要改的。比如某一天mmdet到了2.26.0文档里写着需要mmcv-full 1.4.0那你就把本文第三部分的git checkout v1.3.17换成git checkout v1.4.0然后把mmdet的安装命令从v2.19.0改成v2.26.0其他步骤不变。不要一上来就盲装新版本。我的建议是先把你需要用到的模型功能对照一下新版本的release notes确认没有破坏性变更再决定升不升级。做研究做工程稳定跑通比什么都重要。5.2 换版本时的三个注意事项第一不要在原环境上直接pip install -U mmdet覆盖升级。不同mmdet版本对应的mmcv依赖可能不同覆盖升级容易留下不可控的环境残留。最好的做法是新建一个conda环境从零编译一次。第二mmcv的编译版本一定要跟着mmdet的要求变。你不能用mmcv 1.3.17去配一个新版本mmdet即使它要求的mmcv是一个更高的版本。版本号不匹配模型里的算子接口就会对不上运行时各种诡异报错。第三换版本之前记录一下当前环境的版本信息。比如用pip list导出依赖保留一份文本存档。出了问题以后可以拿新旧环境做对比而不是凭记忆猜。5.3 排错顺序很重要迁移到新版本时如果遇到报错我习惯按下面的顺序排查能省很多时间先用python -c import mmcv; print(mmcv.__version__)确认当前mmcv版本是否在目标版本要求的范围内。再用python -c import torch; print(torch.cuda.is_available())确认GPU可用这是很多人忽略的。然后看报错信息里的关键字如果是cl.exe、vcvarsall一定是编译器环境问题重新检查VS Build Tools如果是CUDA_HOME检查环境变量如果是module not found检查是否装错了mmcv和mmcv-full。最后才考虑源码本身的兼容问题。大多数情况下前面几步就能解决九成的问题。最后补一条我自己一直沿用的习惯把每个环境的信息单独记录到一个txt里包括环境名、Python版本、PyTorch版本、CUDA版本、mmcv版本、mmdet版本、安装日期。Windows环境出问题的时候这种记录能帮你快速判断是不是“版本漂移”而不是去大海捞针。另外安装过程如果中途失败不要急着重装整个环境通常只需要卸载对应包再装一次就行。mmcv编译这条路第一次走最难受只要走过一遍后续也就是改个checkout版本号的事。