ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

MMDetection3D环境配置指南:版本匹配、安装步骤与报错排查

MMDetection3D环境配置指南:版本匹配、安装步骤与报错排查 从最开始接触MMDetection3D那天起我就知道这不会是一个简单pip install就能解决的环境。真正让我头大的不是点云模型的结构不是数据预处理流程而是MMDetection3D与MMDetection之间的版本匹配——版本没对上import阶段直接报属性错误运行阶段出现未定义符号最夸张的一次编译到一半整台机器卡死。这种问题一旦出现排查所花的时间往往比跑模型还多。这篇文章就把我在这条路上踩出来的版本匹配逻辑、安装顺序、测试验证方法全部摊开适合第一次搭3D检测环境、或者之前被版本问题劝退的开发者参考。我会从依赖链的本质讲起给出可以直接照抄的版本组合和安装命令最后再列一组真实运行中会遇到的报错和对应解法。文章不绕弯子全部是实际操作过的内容。1. 版本地狱的根源OpenMMLab组件间的强制依赖链1.1 mmcv、mmdet、mmdet3d与mmengine各管哪一块很多人在安装时报错后第一反应是“我是不是装错了包”其实真正的问题是没搞明白OpenMMLab这套生态的分工。MMDetection3D不是独立存在的它下面压着一整套多层依赖最底层是PyTorch和CUDA往上是MMCV和MMEngine再往上是MMDetection最后才是MMDetection3D。MMEngine负责训练和测试的流程引擎包括Runner、Hook、日志、权重存储这些基础设施。MMCV是计算机视觉的基础工具库里面既有网络层、数据变换、文件IO这类纯PyTorch代码也有NMS、ROIAlign、点云算子这类需要C和CUDA编译的算子。MMDetection是基于MMCV和MMEngine实现的2D目标检测库提供了一系列2D检测器的模型和训练配置。MMDetection3D则是在MMDetection基础上扩展出3D检测、分割、单目深度估计等能力。理解这个层级关系很重要因为版本报错九成以上不是MMDetection3D本身的bug而是它依赖的下层组件版本对不上。比如MMDetection3D底层要用到MMDetection里的某些检测头代码MMDetection要用到MMCV里某个算子MMCV的算子是针对特定PyTorch和CUDA版本编译的。任何一环脱节整个链就会断。1.2 版本不匹配时的典型崩溃长什么样我自己第一次装环境时用的是网上零散搜出来的命令结果装完MMDetection3Dimport mmdet3d直接就红了。报错是这样的AttributeError: module mmcv.cnn.bricks.transformer has no attribute PatchEmbed还有一次是ImportError: cannot import name build_poss_embed from mmdet.models.utils这两类错误都有一个共同点报错位置在import mmdet3d的第一行但真正元凶却在mmcv或mmdet里。原因是MMDetection3D在导入时会调用MMDetection和MMCV里的模块接口如果底层版本的接口签名变了、函数改名了、算子没编译出来它就会在最入口的地方炸开。还有一个更隐蔽的场景命令行不报错但跑训练时突然提示某个算子找不到对应的CUDA kernel或者loss开始出nan。这种往往不是模型代码问题而是mmcv编译时用的PyTorch/CUDA版本和当前环境不一致导致算子在设备上执行了错乱的结果。1.3 官方版本矩阵是唯一的“真理来源”所以我个人的建议是不要凭网上的博客结论拍板装哪个版本一切以官方文档的版本矩阵为准。MMDetection3D的GitHub仓库里README.md和docs/get_started.md会在每次发版时更新对应的依赖版本setup.py里也会有严格的版本约束。比较核心的几个约束是MMDetection3D对MMDetection有明确的版本区间要求比如mmdet3.0.0,3.2.0你用新版的mmdet 3.3.0就可能出现接口不兼容。MMDetection3D对MMCV的要求通常写成mmcv2.0.0,2.2.0如果直接装到最新版很容易越过上限。MMEngine版本也有上下限。PyTorch版本影响MMCV预编译包的选择1.10、1.13、2.0、2.1各有不同的预编译链接。版本矩阵不是摆设它实际上是把所有组合测试过一遍后保出来的“安全范围”。我后来养成了一个习惯每建一个环境先打开对应的官方get_started文档把里面标出来的torch、mmcv、mmdet、mmengine版本记下来再开始动手。2. 装环境前先做选择题版本组合怎么定2.1 显卡驱动、CUDA、PyTorch三者的隐性绑定很多人对CUDA的认知是“装了驱动就装了CUDA”这其实是个误区。nvidia-smi右上角显示的CUDA Version表示的是当前显卡驱动最高支持的CUDA版本不代表系统里已经安装好了对应的CUDA Toolkit。PyTorch安装包本身就内置了CUDA运行时所以很多训练任务不装独立CUDA Toolkit也能跑。但一旦涉及自己编译mmcv、编译CUDA算子系统里就需要有和PyTorch内置CUDA版本一致的nvcc。版本对不上时最常见的错误是nvcc fatal: The version (xxx) of the host compiler (gcc) is not supported或者是编译完了以后跑训练报RuntimeError: CUDA error: no kernel image is available for execution on the device因此正确的检查顺序是先看nvidia-smi确认驱动支持到哪个CUDA主版本。再看PyTorch官方给出的CUDA版本要求选择一个不大于驱动支持上限的版本。根据PyTorch版本去选择MMCV预编译包对应的CUDA版本。只要驱动不是古董级一般用CUDA 11.8或12.1都没问题。真正容易踩坑的是PyTorch装的是cu118但mmcv预编译包选了cu121两者虽然都能跑一旦遇到算子内部对CUDA版本敏感就会出幺蛾子。2.2 怎么读官方版本的映射关系MMDetection3D官方文档会给出一个兼容表类似这样MMDetection3DMMDetectionMMCVMMEngine1.0.03.0.02.0.00.7.41.1.03.0.02.0.00.8.31.2.03.1.02.0.00.8.41.4.03.2.02.0.0,2.2.00.10.1,0.11.0这个表不是给你随便挑一项就完事而是让你理解版本区间是互相咬合的。比如MMDetection3D 1.4.0要求MMDetection 3.2.0MMDetection 3.2.0又可能要求MMCV2.0.0并配合特定PyTorch版本。一张表看过去要确保每一行的依赖都落在对方的要求范围内。在安装时我推荐把主版本定好然后靠pip或者mim去解析。比如我指定安装mmdet3.2.0pip会发现它依赖mmcv2.0.0这时候如果环境里已经有mmcv 2.1.0就会跳过如果有mmcv 1.8.0它可能会尝试自动升级升级失败就直接报依赖冲突。这个行为有时会坑人所以装完以后一定要跑一遍验证检查。2.3 几组我长期在用的稳定组合以我实际跑过业务的经验下面几组组合成功率很高也方便后续复现| 组合名称 | Python | PyTorch | CUDA | MMCV | MMDetection | MMDetection3D | MMEngine | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | 经典稳 | 3.8 | 1.10.0 | 11.3 | mmcv-full 1.6.0 | 2.25.0 | 0.17.1 | 无 | | 新版主流 | 3.9 | 2.1.0 | 11.8 | mmcv 2.1.0 | 3.2.0 | 1.4.0 | 0.10.1 | | 激进尝鲜 | 3.10 | 2.4.0 | 12.1 | mmcv 2.2.0 | 3.3.0 | 1.5.0 | 0.10.5 |经典稳组合的MMDetection3D 0.17.1属于旧架构不需要装MMEngine但MMDetection2和mmcv-full的接口和现在差别很大写新代码会别扭。新版主流组合是2024年我做得最多的组合适配的模型多算子齐全社区反馈也多。激进尝鲜组合适合想用新特性的开发者但要有处理冷门报错的心理准备。无论选哪一组都建议在官方docs/get_started.md里核对一眼因为版本迭代很快没准新版本已经把可选区间扩大了。3. 环境准备Python、conda和编译链的一个都不能少3.1 conda环境与Python版本怎么选我建环境的习惯是conda create -n mmdet3d python3.9 -y conda activate mmdet3d选Python 3.9的理由很现实OpenMMLab的大部分模型和算子都明确支持3.8到3.103.9踩坑最少。Python 3.7太老新版本PyTorch已经不再提供轮子Python 3.11虽然现在也能跑很多新库但遇到一些老版本的mmcv源码编译时会有语法兼容性问题。conda环境建议用Miniconda而不是完整Anaconda启动更快依赖更干净。创建环境后第一时间设置国内pip镜像不然装PyTorch和mmcv时下载能让人等到怀疑人生pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple这里要注意pip源只影响PyTorch之外的包。PyTorch本身要从官方源或对应的CUDA源安装如果用了清华源默认拿到的可能是CPU版本这个坑后面会说。3.2 安装PyTorch的正确打开方式PyTorch版本的选择必须和之后MMCV预编译包匹配。拿新版主流组合举例我需要的是CUDA 11.8版本的PyTorch 2.1.0官方命令是pip install torch2.1.0 torchvision0.16.0 torchaudio2.1.0 --index-url https://download.pytorch.org/whl/cu118这行命令会把CUDA 11.8对应的PyTorch相关包都装好不需要单独安装cudatoolkit。装完以后一定要先验证GPU是否可用python -c import torch; print(torch.__version__, torch.cuda.is_available())如果输出2.1.0cu118 True就说明正常。如果torch.cuda.is_available()是False要么装成了CPU版本要么是PyTorch的CUDA版本和驱动不兼容。这时候不要继续往下装mmcv不然后面编译和运行都会出问题回头排查成本更高。3.3 提前装好编译工具后面能省一大半心MMDetection3D在安装时会对mmcv中的算子做一轮检查如果发现算子缺失、或者环境里是纯mmcv-lite版本它会尝试直接编译。编译依赖三样东西C编译器、ninja、合适的setuptools。Ubuntu系统一般先确认gcc/g版本gcc --version如果你的CUDA版本是11.8GCC在9到11之间基本都能配合CUDA 12.x对GCC 12/13的支持开始变好。但GCC版本太高可能触发nvcc的“host compiler not supported”报错所以别盲目升级系统GCC。推荐安装ninja来加速编译pip install ninja1.11.1ninja比make快很多而且并行度更高。还有一个容易被忽略的依赖是setuptools。新版setuptools70以上对老版mmcv的setup.py不兼容会报类似AttributeError: module setuptools has no attribute Distribution的错解决办法是装一个不算太新的版本pip install setuptools70.0.0这些内容看起来和版本匹配没关系但它们确实参与了“能不能编译出正确算子”的整个过程。我把它们当作环境准备里的隐性版本约束先把它们固定住后面编译mmcv才不会莫名其妙翻车。4. MMCV安装这条链路里最决定生死的一环4.1 从mmcv-lite到mmcv-full再到mmcv 2.x如果你搜过多年前的教程会看到三种mmcv的包名mmcv-lite、mmcv、mmcv-full。这三个名字是历史遗留产物现在很多人还在混用导致指令抄错。mmcv-lite是不含编译算子的轻量版只包含纯Python代码正常跑3D模型基本不可用。在mmcv 1.x时代mmcv也是不带算子的mmcv-full才是带完整算子的版本所以官方安装文档里写的是pip install mmcv-full。在mmcv 2.x时代官方决定不再区分full和lite统一断点包名改成mmcv且默认包含编译算子。这个变化直接带来一个问题如果你照着旧文档装运行pip install mmcv-full2.1.0会发现找不到这个包或者你装了mmcv2.1.0却仍然看到一个位置写着mmcv-lite根本装不出来。所以看到版本号是2.x时记住一句话包名就叫mmcv后面别带full。4.2 用mim拉预编译包别再拿pip硬撞我自己用过最顺手的安装方式是使用OpenMMLab自己的包管理器openmimpip install -U openmim mim install mmcv2.1.0mim会自动检测当前环境里的PyTorch版本和CUDA版本然后选择对应的mmcv预编译轮子。它不会让你做选择题也不会出现编译报错整个过程通常在几分钟内完成。如果你希望精确指定某个CUDA版本也可以直接访问官方预编译包索引地址pip install mmcv2.1.0 -f https://download.openmmlab.com/mmcv/dist/cu118/torch2.1/index.html这种方式的底层逻辑是mmcv的编译是细粒度算子编译和PyTorch的CUDA版本强相关官方直接为每个PyTorchCUDA组合打好wheel省去本地编译时间。我在两年前编译过一次mmcv-full等了大半小时还经常因为内存不够挂掉所以现在只要有预编译包可选我绝对不源码编译。4.3 源码编译时的内存、超时与算子核查但总有情况让你必须走源码编译比如没有对应组合的预编译包或者你要改mmcv里的算子做实验。源码编译mmcv的正确姿势是git clone -b v2.1.0 https://github.com/open-mmlab/mmcv.git cd mmcv MMCV_WITH_OPS1 pip install -e .这里有个容易踩的点MMCV_WITH_OPS1这个环境变量不能省否则会按轻量模式安装等于装了一堆没有算子的壳。编译过程需要下载一些依赖比如kornia、addict、yapf等建议在clone之前就确认网络能正常访问GitHub和PyPI。国内用户如果不方便访问GitHub可以用码云等GitHub镜像站去clone速度会快很多。源码编译最大的风险在内存和swap。mmcv的算子编译在并行编译时很容易把内存占满物理内存不到8G的情况下建议在编译命令前面加MAX_JOBS2 pip install -e .限制并发数牺牲速度换稳定。如果编译到一半出现Killed基本就是内存爆了调大swap或者减少MAX_JOBS再试。编译完成后马上验证算子是否真的编译出来了python -c from mmcv.ops import nms; print(nms ok:, nms)如果这个能过说明mmcv这层稳了下一步才轮到MMDetection和MMDetection3D。5. MMDetection与MMDetection3D的安装策略先装哪个真的会踩坑5.1 MMDetection官方推荐流程与我的实际操作差异官方文档的顺序是先装MMDetection再装MMDetection3D。这个顺序我在实际操作时也建议严格遵守原因不是硬性依赖而是两个库在安装时都会做环境检查如果先装MMDetection3D再去依赖解析它可能会把MMDetection自动替换成它认为合适的版本这个“我认为合适”未必是你原来想要的。MMDetection的源码安装方式git clone -b v3.2.0 https://github.com/open-mmlab/mmdetection.git cd mmdetection pip install -r requirements/build.txt pip install -e .pip install -e .是源码可编辑安装好处是代码直接看得见改得着。也可以用pip install mmdet3.2.0省事一点但在调试模型或者准备二次开发时我建议用源码安装因为MMDetection3D里的很多模型会从MMDetection import代码进来能直接看源码比自己猜接口要高效得多。5.2 MMDetection3D源码安装的完整命令序列MMDetection3D的源码安装方式和MMDetection几乎对称先clone指定分支再装依赖再可编辑安装git clone -b v1.4.0 https://github.com/open-mmlab/mmdetection3d.git cd mmdetection3d pip install -r requirements/build.txt pip install -e .这里有一个细节MMDetection3D的源码安装会再次触发对mmcv算子的检查如果某个自定义算子在mmcv.ops里找不到它会尝试启动编译。也就是说mmcv装得不正确这一步会跟着挂掉。安装本身不难真正难的是安装完之后怎么确认这个环境是真的能跑而不是“没报错但一跑就抽风”。我习惯做三层导入验证。5.3 三层导入验证快速判断环境是真通还是假通第一层验证纯PyTorchpython -c import torch; print(torch.__version__, torch.cuda.is_available())第二层验证MMCV和MMEnginepython -c import mmcv; print(mmcv, mmcv.__version__) python -c import mmengine; print(mmengine, mmengine.__version__)第三层验证MMDetection和MMDetection3Dpython -c import mmdet; print(mmdet, mmdet.__version__) python -c import mmdet3d; print(mmdet3d, mmdet3d.__version__)如果第三层报错不要只盯着MMDetection3D看。回到第二层检查mmcv的算子和版本是否正常这是最典型的排查路径。还有一种情况是环境本身能import但pip check会告诉你某个包被自动降级了pip check这个命令会把环境里所有依赖不满足的包列出来我每次装完环境都要跑一次能看到类似mmdet3d 1.4.0 requires mmdet3.2.0, but you have mmdet 3.3.0的信息。很多幽灵问题其实在pip check面前藏不住。6. 跑通第一个3D检测Demo数据、命令与可视化确认6.1 准备测试数据官方demo文件就够用环境装好以后别急着训练自己的数据先用官方demo把流程跑通。MMDetection3D仓库里带了demo用的KITTI数据文件占用空间很小适合做的事就是验证模型能否正常做前向推理。在仓库根目录执行ls demo/data/kitti/正常情况下能看到一个kitti_000008.bin或类似命名的点云文件。如果没有可以使用官方脚本下载demo数据。这一步不需要准备完整数据集跑demo足够。还需要下载对应的预训练权重。以PointPillars为例官方releases里能找到对应KITTI数据集的权重文件把权重放到一个固定目录比如mkdir checkpoints # 下载权重到 checkpoints/ 目录6.2 一次完整的pcd_demo命令使用demo/pcd_demo.py做单帧点云检测命令长这样python demo/pcd_demo.py \ demo/data/kitti/kitti_000008.bin \ configs/pointpillars/pointpillars_hv_secfpn_8xb6-160e_kitti-3d.py \ checkpoints/hv_pointpillars_secfpn_6x8_160e_kitti-3d_20220301_xxx.pth \ --out_dir demo_output \ --device cuda:0参数说明一下第一个参数是输入点云文件。第二个参数是模型配置文件它会指定使用什么模型、什么数据预处理、什么类别数。第三个参数是预训练权重路径。--out_dir指定可视化结果的输出目录。--score-thr可以调整置信度阈值默认0.5想看到更多框可以调低到0.3。跑完以后demo_output目录下会出现可视化的点云检测结果通常是ply或png格式。如果没指定输出目录有些版本会直接显示可视化窗口。6.3 从可视化结果里能看出哪些真问题看到点云图里出现3D框不算完我一般会检查三件事第一类别框的数量和置信度是否合理。如果所有框的置信度都低得离谱比如低于0.3说明权重加载或者类别配置有问题需要检查--score-thr和config里的class_names是否一致。第二框的坐标和朝向是否贴合点云。如果框漂在半空或者扎进路面通常是config里的point_cloud_range和权重训练时的设置不匹配常见于直接把官方权重用到自己处理过的点云上。第三程序本身有没有警告输出。比如模型输出头说“this model uses fp16 but no fp16 is set”这类提示不影响演示但会影响后续训练效率。如果能从点云可视化里看到像样的car框和pedestrian框说明从版本匹配、算子编译、权重加载到前向推理全链路都是通的。到这一步环境安装这个事才算真正画上句号。7. 测试期间最常遇到的报错清单与排查思路7.1 import阶段undefined symbol与属性找不到undefined symbol一词经常出现在import mmcv或mmdet3d时报错中。它本质是某个C扩展库在被加载时引用了别的库里的符号但那个库里没有提供该符号。最常见的诱因是mmcv编译时用的PyTorch版本和当前环境的PyTorch版本不一致。比如你用cu118 PyTorch 2.0编译的mmcv后来把PyTorch升级到了2.1没重装mmcv就有可能出现这种问题。解决办法不是去搜索undefined symbol本身而是把mmcv卸载干净后重装pip uninstall mmcv -y mim install mmcv2.1.0属性找不到类报错比如module object has no attribute xxx一般是库的接口版本错位。我见过最多的是新版mmdet的模型定义里已经改名了而MMDetection3D还在按旧名字import。这时候回看版本匹配表确保三大框架版本同时落在同一个兼容区间比硬改源码靠谱。7.2 编译阶段gcc、ninja、setuptools连环坑源码编译阶段的报错风格完全不同于import阶段经常是整屏的编译输出。常见的有error: unrecognized command-line option -stdc17这种是GCC版本太低连C17都不支持升级GCC即可。反过来还有一个坑nvcc fatal: The version (13.1) of the host compiler (gcc) is not supported这是GCC版本太高高于当前CUDA的nvcc支持表。建议先看nvcc支持的GCC上限再决定是用update-alternatives切换GCC版本还是在conda环境里安装指定版本的gxxconda install gxx_linux-649 -c conda-forge还有一类编译期问题来自ninja和setuptools。老版本mmcv源码遇到新版setuptools会直接在解析版本时崩溃报错信息像AttributeError: module setuptools has no attribute Distribution。我在前面已经提过装好setuptools70.0.0就能避开。7.3 运行阶段显存、维度、权重加载问题环境装通后训练阶段还有几个高频报错。CUDA out of memory最常见。MMDetection3D的3D模型默认配置经常是为多卡环境设计的比如8卡batch size6单卡照搬当然爆显存。解决办法是改samples_per_gpu1、降低num_points或者减小输入体素大小而不是硬加batch。size mismatch for xxx.weight: copying a param with shape torch.Size([...]) from checkpoint说明模型结构和权重不是同一个config产生的。常见于你换了backbone但没换对应权重这时候要回到config和权重文件匹配这个根本问题。还有一种比较特殊显存够用但训练在前几轮就报assert center ! -1或类似三维语义相关的错误。这通常是数据预处理配置和实际输入点云范围不匹配需要检查point_cloud_range、voxel_size、max_num_points这些参数。7.4 重建环境时如何防止旧缓存干扰很多人一遇到奇怪问题就选择“重建环境”但重建后的环境仍然自带一堆缓存导致问题复现。我分享一个比较彻底的清理过程conda remove -n mmdet3d --all -y pip cache purge然后重新建环境重新安装。还有一个经常被忽略的干扰源是PYTHONPATH。如果之前你设置过export PYTHONPATH/path/to/mmdetection3d换成新环境后import到的可能还是旧仓库里的代码。检查方式python -c import sys; print(sys.path)看看路径列表里有没有不符合预期的旧项目目录。如果有直接清除对应的环境变量再重装。这个坑特别隐蔽因为所有日志都显示你导入的包是新环境里的但实际import的却是旧代码结果必然是一堆奇怪的版本不匹配。最后说一个我的个人习惯在每个环境装好以后把pip freeze导出一份到文件命名带上日期。以后环境崩掉或者机器要迁移照着文件版本重装一遍最快20分钟复原整个环境。版本匹配这件事本质上就是让每一个依赖都精确落在它该在的位置上抓准了链路3D检测环境一次装通并不难。
返回列表