拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

mmdet3d环境配置全攻略:从CUDA到PyTorch的版本对齐实战

mmdet3d环境配置全攻略:从CUDA到PyTorch的版本对齐实战

如果你正在搜索“mmdet3d环境配置”,大概率你已经经历过或者马上要经历这样的场景:按照GitHub上的Official Installation文档一步步操作,结果在import mmdet3d时报出一连串底层错误;或是查了一晚上资料,最后发现只是mmcv版本号差了一位小数点,又得推倒重来。我把mmdet3d这套环境在全新机器上反复配过不下十次,今天这篇就把整个过程拆开揉碎,从驱动、CUDA、PyTorch、mmcv、mmdet到mmdet3d,一条链路全部讲清楚,顺便把那些网上教程最不爱写的“为什么”也一并补齐。这篇文章适合刚入门3D目标检测、想在本地跑起PointPillar/BEVFormer等模型的新手,也适合已经被版本问题折磨到怀疑人生的同学。

1. 为什么mmdet3d环境配置这么难:整条工具链都在等你对齐版本

1.1 它不是装一个包,是装一整条工具链

普通Python库的环境配置,往往就是pip install xxx一行命令的事。但接触过mmdet3d的朋友都会有同感:它不仅是装一个包,而是装一整条工具链。mmdet3d是OpenMMLab系列里负责3D目标检测、单目3D检测、点云分割等任务的上层框架,它依赖于mmdet,mmdet又依赖于mmcv,而mmcv作为整个生态的底层基础设施,提供了大量高度优化的2D/3D算子实现。

这里要特别注意:mmcv这个包在安装时不仅仅做Python代码的拷贝,它内部很多核心模块是C++和CUDA写的,需要通过编译器生成对应平台的动态库。这就意味着,你的PyTorch版本、CUDA版本、编译器和显卡驱动,任何一环不对齐,最后的行为都会奇奇怪怪——轻则import报错,重则编译过了但运行时直接段错误崩溃。

我见过不少同学绕开conda直接在系统Python里乱装,最后把系统自带的Python搞坏。这里还是那句话:mmdet3d环境配置这件事,本质上不是装包问题,是一次完整的工具链集成,你每一步的选择都在为后面的步骤定基调。

1.2 版本不齐的典型报错:一眼就能判断哪一环出了问题

这些年在各种交流群里帮人 debug,发现版本不对齐导致的报错高度集中在几个特征上,这里列出来,你以后遇到可以先对照排查:

报错特征通常原因方向
ModuleNotFoundError: No module named 'mmcv'mmcv未安装,或没装进当前conda环境回到mmcv一步
ModuleNotFoundError: No module named 'mmcv.ops'装了mmcv而不是mmcv-full,或mmcv版本和mmdet3d不匹配重装mmcv-full
ImportError: /lib/x86_64-linux-gnu/libstdc++.so.6: version GLIBCXX_3.4.29 not foundgcc版本过低,或conda环境的libstdc++和系统不一致升级gcc或修复conda的libstdc++
undefined symbol: _ZN2at8Tensor...这类链接错误mmcv编译时的PyTorch版本和运行时的PyTorch版本不一致统一PyTorch版本重编mmcv
编译时报CUDA_HOME not found or invalid环境里没有CUDA编译器或路径未设置安装CUDA Toolkit并设置环境变量
编译过程中直接被Killed内存不足或ninja并发过高限制编译并行度
运行时InvalidDeviceFunctionCUDA算力与编译参数不符设置TORCH_CUDA_ARCH_LIST

这个表基本概括了90%的问题。下面开始正式配置时,我会逐步解释为什么会遇到这些问题,以及怎么从源头避免。

2. 动手前先锁定三个版本:CUDA、PyTorch、Python都别乱选

2.1 先看驱动上限,再决定CUDA版本

很多教程上来就让你装CUDA,这是典型的乱指挥。你不需要自己安装完整的CUDA Driver,因为显卡驱动已经包含了运行时所需的底层支持。你要做的是先确认当前驱动能支持什么版本的CUDA。

在终端里执行:

nvidia-smi

看右上角的CUDA Version,比如显示CUDA Version: 12.4,意味着你的驱动最高支持CUDA 12.4,向下兼容所有更早版本,包括11.6、11.7等。这意味着哪怕只装CUDA 11.7的PyTorch版本,驱动层面也完全没问题。

反过来,如果一台老机器的驱动很旧,比如只有CUDA 10.2支持,那装新版PyTorch就必然报错。这一步花30秒确认,就能避免后面所有驱动不兼容的坑。

2.2 PyTorch往下一级级版本联动:一张表讲清楚

PyTorch是这一整套链路里最核心的“版本锚点”。因为mmcv-full的预编译包、mmdet、mmdet3d,都要围绕PyTorch版本来选。我把几个实测稳定、资料最全的组合整理成了表,你直接照着选一组就好:

组合方案PythonPyTorchCUDAmmcv-fullmmdetmmdet3d
老牌经典(KITTI等旧项目常用)3.81.10.011.31.6.12.26.00.17.1
稳如老狗(本文主讲)3.81.11.011.71.7.22.28.21.0.0rc6
较新可用3.91.13.111.71.8.22.28.21.1.1
新生态(OpenMMLab 2.x)3.92.1.011.82.2.03.3.01.5.0

上表中第二行的组合是我个人最推荐的。因为mmdet3d 1.0.0rc6对应的教程、博客和相关模型权重最为丰富,很多你现在会搜到的“mmdet3d踩坑”大多基于这一套。而第四行OpenMMLab 2.x的组合虽然版本新,但改动较大,许多旧配置代码不通用,新人踩到问题后资料也少,不建议作为第一套入门配置。

2.3 为什么我建议新手别用最新版本

这里展开说下我的体会。很多朋友习惯不管什么包都装最新的,这种“求新”心态在mmdet3d环境上特别容易翻车。

原因有几个层面。第一,新版本的开源生态往往存在过渡期,比如mmcv 2.x去掉了mmcv-full的命名,学习资料里大量命令在1.x和2.x之间根本不能混用,你查到的教程很可能直接失效。第二,新版本通常需要更新的显卡驱动、更现代的GCC版本,甚至需要重构一些模型代码,这些都对新手很不友好。第三,OpenMMLab生态有一个特点,每个版本的mmdet3d实验里都锁定了对应的mmcv和mmdet,你拉最新的代码跑官方模型不一定能复现论文精度。作为第一套环境,最保守的组合反而是最快的路线——先跑通,再求新。

所以我的建议很直接:照着“稳如老狗”方案来,把PyTorch 1.11和mmcv-full 1.7.2作为你的基线,后续想升级整套环境,再做单独的新环境测试。

3. 创建conda环境:Python版本和基础依赖的细节一个都不能少

3.1 conda强隔离:别在base环境里硬刚

我第一套mmdet3d环境就因为嫌麻烦直接装在base环境里,结果和实验室服务器上已有的TensorFlow、老版CUDA工具链撞了个天昏地暗,最后花了整整半天清理。后来才养成习惯:只要是做深度学习项目,一律新建独立conda环境。

创建命令很简单:

conda create -n mmdet3d python=3.8 -y conda activate mmdet3d

这里选了Python 3.8。原因不是3.8有多新,而是因为OpenMMLab系列在Python 3.8上的兼容性测试做得最充分,并且绝大多数常见依赖包都能直接找到对应版本。如果你选的Python版本太高,比如3.11以上,很多编译型依赖在安装时容易踩到底层兼容问题。

之后所有安装操作都在这一个环境里进行,和系统的其他项目互不干扰。这样即使环境搞坏了,也只需要删掉环境重来,不会波及日常使用的其他软件。

3.2 Python版本、numba和libGL:最容易忽略的三个依赖

激活环境后,很多人直接就去装PyTorch和mmcv了,结果后面跑模型时被两个不起眼的依赖卡住。这两个依赖就是numba和libGL。

numba是很多点云处理逻辑用到的JIT编译库,如果你直接pip install numba,经常会出现llvmlite版本冲突,或者运行时报告cannot link这类错误。稳妥的做法是用conda统一安装:

conda install numba -c conda-forge -y

conda会自动帮你选择与当前环境匹配的llvmlite版本,省掉一堆麻烦。

libGL这个问题更隐蔽。当你的代码里用到open3d等库处理可视化时,在新版Ubuntu服务器上经常报错:

ImportError: libGL.so.1: cannot open shared object file

这是系统缺少OpenGL基础库导致的。解决办法:

sudo apt update sudo apt install libgl1 libglib2.0-0 -y

这个坑和mmdet3d本身无关,但几乎每个用点云可视化的人都会碰到,提前装好能避免后面验收demo时的意外中断。

3.3 配置pip源和CUDA环境变量,编译前必做

国内网络环境下,建议先把pip源切换成清华源,否则后面下载依赖会非常痛苦:

pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

然后是CUDA环境变量。如果你后面需要源码编译mmcv,这一步躲不掉。mmcv在编译时需要找到nvcc编译器,它依赖CUDA_HOME这个环境变量来定位CUDA安装目录。你需要在当前终端里设置:

export CUDA_HOME=/usr/local/cuda export PATH=$PATH:/usr/local/cuda/bin export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64

这里有个容易混淆的点:通过conda安装的PyTorch自带的cudatoolkit,通常只是运行时依赖,不一定包含完整的编译器工具链。如果nvcc --version提示找不到命令,那就需要额外安装CUDA Toolkit,或使用conda install -c nvidia cuda-toolkit来补全编译器。否则后面编译mmcv时,第一步就会报CUDA_HOME not found or invalid。

由于这些export命令只对当前终端生效,建议把它们写进~/.bashrc或者每次重新打开终端后手动执行一遍,不然换了一个终端窗口就“失忆”了。

4. mmcv-full这一关:预编译、源码编译和最容易翻车的三个原因

4.1 优先用MIM装预编译包,省时又省心

mmcv的安装是整个环境配置里风险最高的一步,但也是最不需要硬碰硬的一步——前提是你会用OpenMMLab官方推出的包管理工具MIM。

pip install openmim -y

装好MIM之后,安装mmcv-full还能避开一大半坑:

mim install mmcv-full==1.7.2

MIM和普通pip的区别在于:它会自动检测当前环境里的PyTorch版本和CUDA版本,并从OpenMMLab的预编译源里挑一个匹配的wheel下载。这能大大降低版本错位导致的问题。

如果你的PyTorch和CUDA组合比较常见,预编译包基本都能直接匹配,整个安装几分钟就完成了,完全不用碰源码编译。这里建议优先用MIM,只有mim找不到对应预编译包的时候,才考虑手动从源码编译。

4.2 源码编译的原理:mmcv里的算子为什么必须编译

理解源码编译的原理,你才知道为什么这一环容易出问题。mmcv不只是一个纯Python框架,它里面的很多算子是直接用C++和CUDA写的,例如点云体素化(voxelization)、稀疏卷积、RoIAlign、BEV Pooling等。这些算子在安装时需要由nvcc和g++编译成动态库,Python层只需要调用这些接口。

所以,一旦你走源码编译这条路,实际是在做一次实实在在的C++/CUDA编译,这也就引入了一系列对系统环境的要求:GCC版本、CUDA Toolkit、显存无关的编译器配置等。这也是为什么很多人装mmdet、mmdet3d都很快,唯独在mmcv这里卡了半天——因为它根本不是装包,而是在做宿主环境的完整工具链体检。

如果确实需要手动编译,命令是:

pip install mmcv-full==1.7.2 --no-cache-dir

这会拉取源码并在本地编译,耐心等待即可。

4.3 编译翻车的三个高频原因及逐一定位

如果你走上了源码编译这条路,那么大概率会遇到下面三个问题,我逐一说明定位方法。

第一个:GCC版本过高导致编译错误。新版Ubuntu自带的GCC 11在编译mmcv 1.x时经常报出莫名其妙的内部错误。解决办法是安装并指定使用GCC 9:

sudo apt-get install gcc-9 g++-9 -y export CC=/usr/bin/gcc-9 export CXX=/usr/bin/g++-9

然后重新执行编译命令。这个坑叫“版本新但未必兼容更好”,编译工具链和编译目标必须匹配。

第二个:内存不足导致进程被Killed。mmcv源码编译会启动很多并行编译任务,如果机器内存不够大,就会出现进程被系统直接终止。解决方法是限制并行度:

export MAX_JOBS=4

如果你用的是ninja构建,还可以额外设置:

export NN=1

这两个环境变量可以大幅降低同时编译的文件数量,让编译过程更保守、更稳定。

第三个:CUDA_HOME未找到或指向错误。前面第3节提到过,如果你没有把CUDA路径export到环境变量中,这里就会报:

RuntimeError: CUDA_HOME not found or invalid. Please set CUDA_HOME to the root of your local CUDA installation.

解决办法就是把那段export命令执行一遍,然后确认nvcc --version能正常输出。如果你希望一劳永逸,可以把这些export写进~/.bashrc文件,这样每个终端窗口打开时都会自动加载。

5. mmdet与mmdet3d安装:版本对照表和自检脚本一步到位

5.1 mmdet3d各版本组合表:按这张表下菜

mmcv-full安装成功之后,剩下两个包就相对轻松了。但别掉以轻心,mmdet和mmdet3d同样有严格的版本对应关系。我在安装新环境时,通常以这份组合表作为基准:

mmdet3d版本对应mmdet版本对应mmcv-full版本备注
1.0.0rc42.25.01.6.1老版本
1.0.0rc62.28.21.7.2本文推荐
1.1.12.28.21.8.2较新
1.5.03.3.02.2.0OpenMMLab 2.x生态

强烈建议你严格按照这张表来安装,不要自己混搭。很多人跑到import mmdet3d这一步时报错,一查,十有八九是拿mmdet3d 1.0.0rc6搭了mmdet 2.14.0,或者拿mmcv 2.x搭了老mmdet3d,这些都是典型的版本错配。

5.2 安装命令:mim方式与源码方式二选一

先装mmdet:

mim install mmdet==2.28.2

然后用源码方式安装mmdet3d。为什么推荐源码方式而不是直接pip install mmdet3d?因为在开发过程中,你经常要查看或修改mmdet3d源码,源码安装会以develop模式挂载到环境里,直接指向本地克隆的仓库,后续改动即时生效,也方便拉更新。而且mmdet3d在源码安装时会执行一些额外的编译和自动代码生成步骤,比直接装release包更可靠。

git clone -b v1.0.0rc6 https://github.com/open-mmlab/mmdetection3d.git cd mmdetection3d pip install -e .

整个过程一般几分钟跑完。如果你看到Successfully installed mmdet3d-1.0.0rc6,说明安装成功。

这里也补充一下mim方式:

mim install mmdet3d==1.0.0rc6

两种方式都可以,但如果你之后想研究代码或改模型,源码安装会更顺手。

5.3 安装完先做自检:三步确认环境真正可用

不少朋友装完就立刻跑到example里跑训练,结果在一堆看似奇怪的地方报错。其实你在跑模型前,花一分钟做个自检,就能把90%的问题提前暴露出来。

先验证PyTorch和CUDA是否可用:

python -c "import torch; print(torch.__version__, torch.cuda.is_available())"

输出应包含True,例如1.11.0 True。若为False,说明PyTorch的CUDA版本和驱动不匹配,回到第2章检查。

再验证mmcv、mmdet、mmdet3d版本:

python -c "import mmcv; print('mmcv', mmcv.__version__)" python -c "import mmdet; print('mmdet', mmdet.__version__)" python -c "import mmdet3d; print('mmdet3d', mmdet3d.__version__)"

三个版本能正常输出,说明基础安装成功。最后再跑一个算子级验证,调用一下mmcv中的CUDA算子,比如RoIAlign的前向计算,确保编译出来的算子在当前显卡上真的能运行。这一步能提前暴露CUDA算力不匹配的深层问题。

6. 跑通第一个Demo:验证安装是否真正成功

6.1 用官方pcd_demo跑一次点云推理

版本自检通过后,最让人兴奋的就是跑一个真正的模型demo了。mmdet3d仓库里的demo/pcd_demo.py可以直接对点云文件做3D目标检测推理。

首先下载模型权重和样例数据:

mim download mmdet3d --config hv_pointpillars_secfpn_8xb6-160e_kitti-3d-3class --dest ./checkpoints

mim会自动把对应的config文件下载到checkpoints目录。然后用点云推理命令:

python demo/pcd_demo.py demo/data/kitti/kitti_000008.bin \ ./checkpoints/hv_pointpillars_secfpn_8xb6-160e_kitti-3d-3class.py \ --checkpoint ./checkpoints/hv_pointpillars_secfpn_8xb6-160e_kitti-3d-3class_6dB76678_20220324_055145_a6c9c879.pth \ --pc-input demo/data/kitti/kitti_000008.bin

看到输出的可视化结果或者检测框标注时,说明你的mmdet3d环境已经真正可用了。

这里和你说一个常见情况:跑demo时如果报KeyError: 'xxx'或者TypeError,通常不是demo代码的问题,而是config文件和mmdet3d工具链版本没对齐。回到版本对照表,逐项核对。

6.2 训练需要准备什么:KITTI数据的组织方式

demo跑通后,很多人会想着直接训练自己的模型,这一步建议提前规划。mmdet3d训练的第一步是数据组织。以KITTI数据集为例,官方脚本要求你把数据下载后按固定格式整理:

mmdetection3d ├── data │ ├── kitti │ │ ├── ImageSets │ │ ├── testing │ │ ├── training │ │ └── ...

然后执行数据转换命令:

python tools/create_data.py kitti --root-path ./data/kitti --out-dir ./data/kitti --extra-tag kitti

转换过程会产生.bin格式的实例信息文件和索引文件。这一步完成后,再运行训练命令:

python tools/train.py configs/pointpillars/hv_pointpillars_secfpn_8xb6-160e_kitti-3d-3class.py --work-dir work_dirs/pointpillars

需要提前提醒的是,KITTI数据集的完整下载体积在20GB左右,训练过程对显存也有要求(PointPillars这类轻量模型8GB显存够跑,但BEVFormer等模型建议16GB以上)。如果只是验证环境,建议先用demo步骤,不要急着上训练。

6.3 运行时踩过的坑和提速诊断技巧

最后一个部分,我把实际使用中踩过、也帮别人排过的几个“隐性坑”集中讲掉,这些坑不看经验真的很难定位。

第一个:运行时突然报CUDA内存错误。这不一定是你显存真的不够,有时是因为程序里多个组件共享了同一个CUDA context,尤其在Open3D的可视化窗口和mmdet3d推理前后切换时容易出现。解决办法是尽量让推理和可视化串行执行,不要在同一进程里交叉调用。

第二个:模型推理速度异常缓慢。如果你发现PointPillars在1080Ti上跑单帧都要一秒以上,可能是CUDA算子效率没跑满,先检查一下mmcv编译时是否针对你的显卡算力做过优化。在编译mmcv之前,可以设置:

export TORCH_CUDA_ARCH_LIST="8.6"

这里的8.6是你的显卡算力,比如RTX 3090对应8.6,A100对应8.0,GTX 1080Ti对应6.1。设置之后,mmcv编译出来的算子会更契合当前显卡,编译产物在运行时也不会因为浮点兼容性问题走兜底路径。

第三个:多环境管理时环境名和项目容易搞混。我的习惯是一个项目对应一个conda环境,命名方式如mmdet3d-kitti、mmdet3d-nuscenes。这样即使某天某个环境装坏了,直接删掉重建,不会影响另一个数据集的实验。

最后一个实操小技巧:整套环境好不容易配好后,一定记得导出一份环境配置备份,方便以后在不同机器上复现:

conda env export > mmdet3d_env.yaml

到了新机器上,直接conda env create -f mmdet3d_env.yaml就能恢复环境。当然,由于不同机器驱动不同,恢复到新机器后还是需要微调CUDA相关部分,但至少Python包这一层的版本组合不会乱掉。

这套环境配置流程,我在多台不同显卡、不同系统版本的服务器上走过很多遍,核心心得只有四个字:版本对齐。先看驱动,再定PyTorch,再选mmcv,最后装mmdet和mmdet3d,每一步都不要自作主张混搭版本。按这个顺序走下来,稳当地跑通mmdet3d通常只需要半个下午,祝各位都能顺利跑起自己的第一个3D检测模型。

返回列表