
搞三维重建和视觉 SLAM 的朋友应该都有过这种经历从官方页面下载 COLMAP 预编译包导入图片跑特征提取CPU 直接满载风扇声大得像要起飞GPU 利用率却纹丝不动。大多数情况下问题就出在预编译环境没有吃到 CUDA 加速。尤其当你用的是围绕 CUDA 深度定制的渲染机器或者在 Ubuntu 22.04 这样的 LTS 环境里自己搭建三维重建管线时自己源码编译一份带 CUDA 支持的 COLMAP 几乎是绕不开的一步。这篇博文就是一份可以直接照着敲的实操记录覆盖 Ubuntu 22.04 下 COLMAP 源码编译、CUDA Toolkit 安装与匹配、显卡架构Compute Capability查询这几个关键环节。整篇内容面向那些已经装好 Ubuntu、驱动也能正常识别显卡但在 CMake 配置和编译阶段反复踩坑的开发者。我会把每一步为什么要这么做讲清楚也会把我在多次重装环境后总结的避坑经验放在对应位置希望能帮你少走一些弯路。1. 安装前必须搞定的三件事1.1 先确认显卡驱动到底正不正常不要一上来就装 CUDA先打开终端跑一句nvidia-smi这一步能帮你省掉后面好几个小时的排查时间。正常情况下你会看到类似下面的输出----------------------------------------------------------------------------- | NVIDIA-SMI 535.154.05 Driver Version: 535.154.05 CUDA Version: 12.2 | --------------------------------------------------------------------------- | GPU Name | Persistence-Mode | Mosaic Mode | | 0 NVIDIA GeForce RTX 4080 | On | Default | ---------------------------------------------------------------------------重点看两个信息右上角的CUDA Version表示当前驱动支持到的最大 CUDA 版本下面GPU Name是你的显卡型号。如果提示command not found说明驱动没有安装或者安装没生效。这时候先别急着编译 COLMAP把驱动装好再说。Ubuntu 22.04 装驱动最省事的方式是通过系统自带的ubuntu-drivers工具sudo apt update sudo ubuntu-drivers autoinstall或者你自己去 NVIDIA 官网按显卡型号下载.run驱动包但我不太推荐新手手动装因为nouveau内核模块没屏蔽好的话很容易在登录界面循环重启。用系统自动安装的驱动版本虽然不一定最新但对编译 COLMAP 来说完全够用。装完重启后再次执行nvidia-smi直到能正常看到显卡信息再继续。nouveau占用 GPU 的问题会导致 nvidia-smi 识别不到设备这一点一定不要忽略。提示如果你的机器是双显卡笔记本还要留意 NVIDIA Optimus 是否正常工作。最简单的验证方式是跑一个 CUDA 的deviceQuery但在这个阶段只要nvidia-smi能列出显卡我们就可以认为驱动层面已经 OK。1.2 显卡架构Compute Capability到底是什么这是整个编译流程里最容易翻车、也最容易被新手忽略的地方。先给你一个生活化类比显卡的 CUDA 核心就像一群只会说方言的人不同代际的 NVIDIA 显卡方言不一样。CUDA 代码在编译时编译器要把通用代码翻译成“对应方言”的机器码这个“方言代号”就是 Compute Capability常见写法有sm_86、sm_89、sm_75等。CMake 在编译 COLMAP 的 CUDA 代码时必须知道你手里的显卡属于哪种架构才能生成正确的 SASS 指令。如果你不做任何设置CMake 可能会尝试探测当前环境里的显卡一旦探测失败它可能退回 CPU-only 编译于是你就得到了一个“能用但慢得感人”的 COLMAP。常见的显卡架构对应关系如下显卡系列架构代号Compute CapabilityCMake 参数写法RTX 20 系列 / GTX 16 系列Turing7.5sm_75RTX 30 系列含笔记本Ampere8.6sm_86RTX 40 系列Ada Lovelace8.9sm_89A100 / H100 数据卡Ampere / Hopper8.0 / 9.0sm_80/sm_90GTX 10 系列Pascal6.1sm_61还有一种查询方式是通过 NVIDIA 官方文档里的 “CUDA GPUs” 对照表输入自己的显卡型号就能查到对应的 Compute Capability。我也建议你在终端里看一眼/proc/driver/nvidia/gpus/目录下的型号码那个结果更贴近当前硬件。注意RTX 40 系列sm_89需要 CUDA 11.8 以上版本才支持编译这也是我们下面选型时要考虑的因素。1.3 CUDA Toolkit 版本怎么选才不打架很多人会直接把nvidia-smi右上角的 CUDA 版本当成系统里已经装好的 Toolkit这里有个常见的混淆点那个版本号只是驱动支持的上限并不代表你已经装了 nvcc 编译器。编译 COLMAP 真正需要的是 CUDA Toolkit里面才包含nvcc、CUDA 运行时库和头文件。我推荐从 NVIDIA 官方 apt 仓库安装这样后续升级和维护都省心。以 Ubuntu 22.04 x86_64 为例先添加官方仓库wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb sudo dpkg -i cuda-keyring_1.1-1_all.deb sudo apt update然后安装你需要的 Toolkit 版本。如果你手里是 RTX 40 系列显卡至少要装 12.x 的 Toolkit因为 11.8 虽然支持sm_89但很多配套库已经不再积极更新后续编译新版本 COLMAP 时坑会比较多。我这里直接装 12.4sudo apt install cuda-toolkit-12-4装完之后把 CUDA 的 bin 和 lib 目录加入环境变量。Ubuntu 22.04 默认的 shell 是 bash我习惯写到~/.bashrc里export PATH/usr/local/cuda/bin:$PATH export LD_LIBRARY_PATH/usr/local/cuda/lib64:$LD_LIBRARY_PATH export CUDA_HOME/usr/local/cuda然后source ~/.bashrc执行nvcc -V确认能看到版本信息。注意/usr/local/cuda是一个软链接指向你实际安装的版本目录这样以后切换 CUDA 版本时会方便很多。2. 编译 COLMAP 前的前置依赖2.1 系统基础依赖一次性装齐COLMAP 不是那种“下载一个二进制文件就能跑”的轻量工具它依赖一大堆底层库。我把 Ubuntu 22.04 上编译 COLMAP 需要的系统包整理成一条命令直接复制执行即可sudo apt install -y \ git \ cmake \ ninja-build \ build-essential \ libboost-program-options-dev \ libboost-filesystem-dev \ libboost-graph-dev \ libboost-system-dev \ libeigen3-dev \ libflann-dev \ libfreeimage-dev \ libmetis-dev \ libgoogle-glog-dev \ libgtest-dev \ libsqlite3-dev \ libglew-dev \ qtbase5-dev \ libqt5opengl5-dev \ libcgal-dev \ libatlas-base-dev这里我想解释几个容易忽略的点。ninja-build是构建系统比默认的 make 在增量编译和并行度上表现要好很多尤其在你反复调整 CMake 参数时Ninja 能省下大量重编译时间。libeigen3-dev是线性代数库COLMAP 的 BA 优化和特征处理都要依赖它如果你之前给其他项目手动装过 Eigen注意别让系统路径里的旧版本干扰。libcgal-dev用于网格化和 Delaunay 三角剖分做三维重建输出 mesh 时必需。这些依赖全部用 apt 安装版本虽然未必是最新但胜在稳定。我曾经纠结于把每个库都手动源码编译到最新版结果耗时耗力最后发现 COLMAP 对基础库版本的容忍度比想象中高系统包完全够用。提示qtbase5-dev是 COLMAP GUI 界面的依赖。如果你只打算用命令行方式跑重建流程不装 Qt 也能编译但 CMake 配置时要用-DGUI_ENABLEDOFF之类的方式关掉。我个人建议还是装上毕竟有时候 GUI 看个稠密点云比命令行方便太多。2.2 手动编译 Ceres Solver避开系统老版本理论上 Ubuntu 22.04 的 apt 源里有libceres-dev但版本往往偏旧而 COLMAP 新版3.8 之后对 Ceres 有功能要求旧版本会导致一些残差块的接口对不上轻则警告重则直接编译报错。所以我建议你直接源码编译 Ceres Solver这里多花 10 分钟后面 COLMAP 编译会顺畅很多。先拉源码并切换到稳定版本git clone https://ceres-solver.googlesource.com/ceres-solver cd ceres-solver git checkout 2.1.0然后创建构建目录并配置mkdir build cd build cmake .. -G Ninja \ -DCMAKE_BUILD_TYPERelease \ -DBUILD_TESTINGOFF \ -DBUILD_EXAMPLESOFF这里关掉测试和示例是为了缩短编译时间毕竟我们只需要 Ceres 的核心库。执行ninja编译然后sudo ninja install。默认安装路径是/usr/localCeres 的头文件和库会分别装到/usr/local/include/ceres和/usr/local/lib。注意Ceres 还依赖gflags如果你在后续编译 COLMAP 时遇到找不到gflags的报错先执行sudo apt install libgflags-dev。另外Ceres 2.1.0 对 Eigen 版本有最低要求Ubuntu 22.04 自带的 Eigen 3.4 正好满足条件不需要额外升级。3. COLMAP 源码编译全流程3.1 获取源码并切换到稳定版本COLMAP 官方仓库地址是https://github.com/colmap/colmap我建议不要直接拉 master 分支因为开发分支经常会有接口变动编译报错了也不容易找到对应方案。我个人用的稳定版本是 3.9.1实测和 CUDA 12.x、Ceres 2.1.0 搭配得很顺git clone https://github.com/colmap/colmap.git cd colmap git checkout 3.9.1如果你在 GitHub 访问上遇到困难也可以在官方 Release 页面下载对应 tag 的源码压缩包效果一样。记住一个原则编译这种大型开源项目稳定版本永远优先于最新开发版本除非你需要某个只有 master 才有的新功能。3.2 CMake 配置中最容易翻车的参数COLMAP 的 CMake 配置是整条链路里最需要细心的一步。我把推荐的配置命令直接放在这里然后逐条解释cd colmap mkdir build cd build cmake .. -G Ninja \ -DCMAKE_BUILD_TYPERelease \ -DCMAKE_CUDA_COMPILER/usr/local/cuda/bin/nvcc \ -DCMAKE_CUDA_ARCHITECTURES89 \ -DCMAKE_INSTALL_PREFIX/usr/local这里的CMAKE_CUDA_ARCHITECTURES就是你第 1.2 节查到的架构参数。RTX 40 系列填89RTX 30 系列填86RTX 20 系列填75。这个参数决定了生成的 CUDA 机器码是给哪一代显卡用的。需要特别强调的是CMake 里的写法不需要带sm_前缀直接写数字就行比如86、89。我还见过有人喜欢写成native让 CMake 自动探测当前显卡架构。这个思路听起来省事但有一个隐患如果编译机器和运行机器不是同一张卡或者编译环境处于没有 GPU 权限的容器里native探测就会失败CMake 会悄然退化成 CPU 版本编译。因此我强烈建议要么手动指定架构要么像下面这样同时指定多个架构-DCMAKE_CUDA_ARCHITECTURES86;89这样编译出来的二进制能在多代显卡上运行代价是编译时间变长、生成的二进制体积变大。如果你的软件要分发给别人用这一招很有用如果只是自己机器上用指定一个架构就够了。另一个隐藏的坑是CMAKE_CUDA_COMPILER。如果你在~/.bashrc里配置了 PATHCMake 通常能自己找到nvcc。但某些情况下比如你安装了多个 CUDA 版本CMake 可能找错编译器导致编译时头文件版本对不上。显式指定nvcc的完整路径能杜绝这种问题。3.3 编译安装与第一次启动验证CMake 配置成功后可以看到终端输出里有一行类似CUDA is enabled的提示确认之后就可以开始编译ninja -j$(nproc)这里的$(nproc)会自动使用你机器的全部 CPU 核心速度最快。但如果你是轻度办公本CPU 发热比较高建议手动限制比如ninja -j4。COLMAP 整个编译过程大概需要 15 到 30 分钟取决于机器性能。如果编译过程中遇到报错先别急着改代码先看下一章的常见问题排查八成能直接对症下药。编译完成后执行安装sudo ninja install安装完colmap命令就会被放到/usr/local/bin/下。执行colmap -h如果能正常打印帮助信息说明安装已经成功。接着执行colmap feature_extractor --help这个命令会打印特征提取模块的参数列表。这一步不仅是验证安装也是在后续重建时查看参数选项的快速入口。4. 编译与运行中的常见问题速查4.1 编译阶段典型报错与解决办法这一节我把实际编译中遇到频率最高的几个问题整理成一张速查表方便你对号入座症状可能原因解决办法CMake 提示Could not find CUDA没有安装 CUDA Toolkit或路径不在默认位置回到 1.3 节安装 cuda-toolkit或手动指定-DCMAKE_CUDA_COMPILER/usr/local/cuda/bin/nvcc编译时报Unsupported gpu architecture compute_XXCMAKE_CUDA_ARCHITECTURES填写格式或数值错误改成数字形式如86、89并确认对应 CUDA 版本支持该架构报错找不到ceres/ceres.h或gflags/gflags.hCeres 未安装或安装路径不在系统搜索路径中跳转到 2.2 节源码编译 Ceres安装libgflags-dev编译过程中内存不足进程被 kill并行编译任务过多降低 ninja 并行数如ninja -j2或临时增加 swap 分区Qt 相关组件缺失GUI 按钮灰色缺少 qtbase5-dev 和 libqt5opengl5-dev回到 2.1 节安装 Qt 相关依赖后重新 cmake在容器内编译时提示nvcc fatal: Unsupported gpu architecture容器里看不到显卡导致探测失败手动指定CMAKE_CUDA_ARCHITECTURES为宿主机显卡对应架构这里我想单独展开说一下 “gzip: stdin: invalid compressed>export LD_LIBRARY_PATH/usr/local/cuda/lib64:$LD_LIBRARY_PATH还有一种情况比较隐蔽你机器上装了多个 CUDA 版本某个库编译时用了高版本运行时却被动态加载到了低版本库。排查方式是用ldd看一下可执行文件的链接情况ldd /usr/local/bin/colmap | grep -i cuda如果发现链接到了不期望的版本可以通过调整LD_LIBRARY_PATH或清理多余版本解决。这个问题的根本原因在于 CUDA 版本管理混乱所以我在第 1.3 节反复强调用/usr/local/cuda软链接来统一入口。如果运行colmap时提示显卡显存不足尤其是处理大型场景时可以先在参数里调低--SiftExtraction.max_num_features或缩小图片尺寸。COLMAP 对显存占用和输入图片大小密切相关这个不属于编译问题但属于新手容易踩的性能坑这里顺带提一句。5. 验证 COLMAP 是否真的在调用 CUDA5.1 三种最直接的验证方式编译完并不是终点还要确认你这份 COLMAP 确实是带 CUDA 加速的。我常用三种方式验证。第一查看 CMake 缓存里 CUDA 相关配置。在 build 目录下执行grep -i cuda CMakeCache.txt如果看到CMAKE_CUDA_COMPILER:FILEPATH/usr/local/cuda/bin/nvcc而且 CUDA 相关的选项都是 ON基本可以确认编译阶段已经启用了 CUDA。第二用nvidia-smi实时监控 GPU 使用率。找一个小数据集运行 COLMAP 的特征提取命令同时在另一个终端执行watch -n 0.5 nvidia-smi在 GPU 加速下你会看到某个进程占用一定的显存和 GPU 利用率。如果 GPU 利用率始终是 0%而 CPU 满载说明 COLMAP 根本没用到 CUDA。第三用时间对比说服自己。分别在 CPU-only 和 CUDA 版本下跑同一个数据集的特征提取与匹配记录耗时差异。一个中等规模的数据集比如 200 张图片CPU 版可能需要几十分钟CUDA 版往往几分钟就能完成差距非常直观。5.2 后续还能做哪些扩展COLMAP 编译好之后我建议你顺手把 Python 绑定pycolmap也装一下。现在很多三维重建脚本都依赖 pycolmap 的 API 来读模型、做特征提取或调用重建流程和命令行工具配合起来非常高效。注意 pycolmap 的版本要和 COLMAP 的版本匹配否则可能出现接口不兼容。另外如果你还需要跑大规模场景重建建议检查一下机器是否有足够的内存和硬盘空间。COLMAP 在稠密重建阶段会产生大量中间文件一个几百张图片的项目轻松占用几十 GB 磁盘空间这个属于数据管理层面的建议但往往比编译本身更影响使用体验。提示如果你手头有多个 CUDA 工具链建议为 COLMAP 单独维护一份环境脚本把 PATH 和 LD_LIBRARY_PATH 固定下来防止其他深度学习框架的 CUDA 运行时干扰 COLMAP 的运行环境。我在实际装机时还有一个小习惯每次编译完这种大型项目都会把 CMake 的配置命令存成脚本放在项目目录里比如build_colmap.sh。这样半年后系统重装、或者换新机器编译时直接拿脚本跑一遍就能复现整个编译过程不需要再回忆那些参数。你以后如果打算维护多台三维重建机器这个小习惯会帮你省下很多时间。