
1. 为什么今天还要折腾Caffe环境如果你最近打算复现一篇老论文或者接手了一个遗留的深度学习项目打开代码仓库发现里面全是.prototxt和.solver文件那你大概率绕不开Caffe。这东西在深度学习框架的上古时代几乎是统治级的存在虽然现在大家张口闭口都是PyTorch和TensorFlow但工业界很多已经落地跑了好几年的模型底层依然是Caffe训练出来的。我身边就有做安防和工业质检的朋友产线上的模型到现在还在用Caffe推理原因很简单稳定、快、部署链路成熟。但问题也恰恰出在这里。Caffe的黄金时代是2014到2017年那个年代的编译环境、依赖版本、CUDA版本跟现在完全不是一回事。你拿一台2024年新装的机器照着当年的教程一步步敲大概率会在某个依赖报错上卡住半天。我自己第一次搭Caffe环境的时候光是protobuf版本冲突就折腾了整整一个下午最后发现是系统自带的版本和Caffe要求的版本打架。所以这篇内容的核心目标很明确帮你在当前环境下用最少的弯路把Caffe跑起来。我会从依赖选型讲起把每个关键决策背后的原因说清楚然后给出经过实测的完整步骤最后把几个高频踩坑点单独拎出来讲。适合两类人看一是需要复现老项目但没接触过Caffe的开发者二是以前用过Caffe但换机器后重新搭建时被环境问题卡住的人。整个过程我会尽量用为什么这么做来解释每一步而不是甩一堆命令让你照抄。需要提前说明的是Caffe的安装方式有好几种——源码编译、Docker镜像、conda安装。这三种我都试过各有各的适用场景后面会详细对比。本文主要走源码编译这条路因为它是理解Caffe依赖关系最透彻的方式也是遇到问题时最容易排查的方式。如果你只是想快速跑个推理Docker可能是更省事的选择我也会给出对应的思路。2. 编译之前必须想清楚的几件事2.1 CPU版还是GPU版这个决定影响后面所有步骤很多人一上来就问怎么装Caffe但更该先问的是我要用CPU还是GPU。这个选择直接决定了你的依赖清单、编译参数和后续能不能跑训练。GPU版需要CUDA和cuDNN编译出来的Caffe可以利用显卡做并行计算训练速度比CPU快几十倍甚至上百倍。但代价是CUDA版本和Caffe的兼容性非常挑剔。Caffe官方最后活跃的版本大概支持到CUDA 8到9左右如果你机器上装的是CUDA 11或12直接编译大概率会报一堆API不匹配的错误。我实测下来CUDA 8.0配合cuDNN 5或6是最稳的组合但这个版本的CUDA在新显卡上又装不了因为新显卡的驱动要求更高版本的CUDA。这就形成一个尴尬的局面新机器装不了老CUDA老CUDA配不了新显卡。所以如果你用的是比较新的显卡比如30系、40系我的建议是先老老实实装CPU版把流程跑通确认代码逻辑没问题之后再考虑用Docker或者找一台老机器来跑GPU训练。CPU版虽然慢但编译过程干净不会因为CUDA的各种版本问题把你劝退。判断方法很简单打开终端敲nvcc --version如果有输出说明装了CUDA再看看版本号。如果版本在9以下可以尝试GPU编译如果是10以上建议直接走CPU路线或者Docker路线。2.2 依赖库的版本选择为什么最新版往往是坑Caffe的依赖清单不算长但每一个都有版本讲究。我列一个表把关键依赖和推荐版本说清楚依赖库作用推荐版本踩坑说明protobuf定义网络结构的数据格式2.6.1 或 3.6.x3.0以上某些API有变化容易编译报错boost提供C基础库支持1.65以下1.70以上部分头文件路径变了glog日志记录0.3.5版本要求不严但别用太新的gflags命令行参数解析2.2.2相对稳定hdf5数据存储格式支持1.8.x 或 1.10.x1.12以上有API变动opencv图像处理3.x4.x的某些接口不兼容BLAS矩阵运算加速OpenBLAS或MKL选一个就行别同时装这张表里的推荐版本不是我随便写的是反复编译失败后总结出来的。核心逻辑是Caffe的代码写于那个年代它调用的API就是那个年代的API。你用最新版的库头文件路径变了、函数签名变了、甚至某些功能被移除了编译自然过不去。举个具体的例子。protobuf从3.0开始把google/protobuf/stubs/common.h里的一些宏定义改了而Caffe的代码里大量引用了这些宏。你装个protobuf 3.20编译到一半就会报未定义的标识符。解决办法要么是降级protobuf要么是手动改Caffe源码打补丁。前者省事后者费劲我一般选前者。还有一个容易忽略的点系统自带的库和手动安装的库可能冲突。比如Ubuntu系统里可能预装了某个版本的protobuf你用apt又装了一个然后手动编译又装了一个最后编译器找到的是哪个版本完全看运气。所以我的习惯是编译Caffe之前先用apt list --installed | grep protobuf查一下系统里有什么该卸的卸干净避免多个版本打架。2.3 三种安装路线的取舍在动手之前先把三条路摆出来对比一下你根据自己的情况选源码编译最灵活能改代码、能调参数、能精确控制依赖版本。缺点是耗时长第一次编译加上解决依赖问题两三个小时很正常。适合需要深入定制或者要理解Caffe内部机制的人。Docker镜像最省事拉一个别人配好的镜像里面环境都是现成的。缺点是镜像质量参差不齐有些镜像里的Caffe版本很老有些缺少GPU支持。适合只想快速跑通、不想折腾环境的人。Conda安装通过conda-forge频道可以装到Caffe命令就一行。缺点是conda版的Caffe可能缺少某些功能模块而且和系统里的Python环境容易冲突。适合做快速原型验证。我个人的建议是第一次接触Caffe走源码编译。虽然麻烦但走完一遍之后你对Caffe的依赖关系、编译流程、配置文件都会有清晰的认识后面遇到问题也知道从哪查。如果你已经用过Caffe只是换机器要重新搭那Docker是更高效的选择。3. 从零开始的完整编译流程3.1 系统环境确认与基础依赖安装我以Ubuntu 18.04为例来走一遍这个版本是Caffe编译成功率比较高的。Ubuntu 20.04也可以但有些包的名字变了需要微调。先确认系统版本lsb_release -a然后安装基础编译工具sudo apt-get update sudo apt-get install -y build-essential cmake git pkg-config这几样是编译任何C项目都需要的。build-essential里包含了gcc、g和makecmake用来生成编译配置pkg-config帮编译器找到库文件的位置。接下来装Caffe的核心依赖。这里我给的命令是经过筛选的把版本冲突的风险降到最低sudo apt-get install -y libprotobuf-dev libleveldb-dev libsnappy-dev \ libopencv-dev libhdf5-serial-dev protobuf-compiler sudo apt-get install -y --no-install-recommends libboost-all-dev sudo apt-get install -y libgflags-dev libgoogle-glog-dev liblmdb-dev注意libhdf5-serial-dev这个包名在有些系统上叫libhdf5-dev如果报找不到就换一个试试。--no-install-recommends是为了避免boost装一堆用不上的推荐包能省不少空间。BLAS的选择上我推荐用OpenBLAS安装简单且性能不错sudo apt-get install -y libopenblas-dev如果你有Intel的CPU并且追求极致性能可以换成MKL但MKL的安装稍微麻烦一些需要去官网下载并配置环境变量。对于大多数场景OpenBLAS够用了。3.2 获取Caffe源码与配置文件调整源码从官方仓库克隆git clone https://github.com/BVLC/caffe.git cd caffe克隆下来之后先别急着编译。Caffe的编译配置是通过Makefile.config控制的仓库里给了一个示例文件Makefile.config.example你需要复制一份并修改cp Makefile.config.example Makefile.config然后打开这个文件逐项检查。以下是几个必须改的地方CPU/GPU开关如果你走CPU路线把# CPU_ONLY : 1前面的注释去掉变成CPU_ONLY : 1。这一行决定了编译时是否链接CUDA库。BLAS配置找到BLAS : atlas这一行改成BLAS : open因为我们装的是OpenBLAS。同时确认BLAS_INCLUDE和BLAS_LIB的路径指向正确OpenBLAS一般装在/usr/include和/usr/lib下。Python路径如果你需要Python接口比如用pycaffe写脚本要确保Python的include和lib路径正确。找到PYTHON_INCLUDE和PYTHON_LIB部分根据你的Python版本调整。比如Python 3.6的话路径大概是/usr/include/python3.6m和/usr/lib/x86_64-linux-gnu/libpython3.6m.so。HDF5路径这是个高频坑点。Ubuntu 18.04的HDF5头文件在/usr/include/hdf5/serial/库文件在/usr/lib/x86_64-linux-gnu/hdf5/serial/。你需要在Makefile.config里把这两个路径加到INCLUDE_DIRS和LIBRARY_DIRS里。具体做法是找到这两行在末尾追加路径INCLUDE_DIRS : $(PYTHON_INCLUDE) /usr/local/include /usr/include/hdf5/serial LIBRARY_DIRS : $(PYTHON_LIB) /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu/hdf5/serial这一步不做的话编译到使用HDF5的模块时会报找不到hdf5.h。3.3 编译过程中的参数调优与并行加速配置改好之后就可以编译了。但在敲make之前先做一件事确认你的CPU核心数用nproc命令查看。然后编译时加上-j参数来并行编译能大幅缩短时间make all -j$(nproc) make test -j$(nproc) make runtest -j$(nproc)make all编译核心库和工具make test编译测试程序make runtest跑测试。如果只是自己用make all就够了后面两个可选。但建议至少跑一下make test确保编译出来的东西是完整的。编译过程中如果报错不要慌先看错误信息的第一行。Caffe的编译错误往往是一连串的但根因通常在最开始那几行。常见的错误类型和处理方式我整理一下找不到头文件说明某个依赖的include路径没配好回到Makefile.config检查对应的INCLUDE_DIRS。未定义的引用链接阶段找不到库文件检查LIBRARY_DIRS和LDFLAGS。protobuf相关错误大概率是版本冲突用protoc --version确认版本必要时降级。内存不足被杀并行编译时如果内存不够系统会杀掉编译进程。减少-j后面的数字比如改成-j2。我实测在一台8核16G的机器上make all -j8大概需要15到20分钟。如果超过半小时还没完可能是某个模块卡住了检查一下是不是在编译OpenCV相关的代码那部分特别慢。3.4 编译后的验证怎么确认真的装好了编译完成后在caffe目录下会生成build/文件夹里面有lib/和tools/。验证分三步第一步检查核心库文件是否存在ls build/lib/应该能看到libcaffe.so、libcaffe.so.1.0.0这些文件。第二步运行Caffe自带的命令行工具./build/tools/caffe如果输出一堆用法说明说明工具编译成功了。如果报error while loading shared libraries说明动态库路径没配好需要把build/lib加到LD_LIBRARY_PATH里或者直接写进/etc/ld.so.conf.d/。第三步如果你编译了Python接口验证一下cd python export PYTHONPATH$(pwd):$PYTHONPATH python -c import caffe; print(caffe.__version__)能打印出版本号就说明pycaffe可用了。如果报ImportError: No module named caffe检查PYTHONPATH是否设置正确以及caffe/python/caffe/目录下是否有_caffe.so文件。4. 那些让我熬夜的报错与解决思路4.1 protobuf版本冲突的完整排查链路这是我遇到最多的坑也是很多人卡住的地方。症状通常是编译时报一堆undefined reference to google::protobuf::...或者运行时报This program was compiled against version X of the Protocol Buffer runtime library, which is not compatible with the installed version Y。排查思路是这样的先确认系统里装了哪些protobuf版本。用dpkg -l | grep protobuf看apt装的用which protoc看当前用的是哪个用protoc --version看版本号。如果发现apt装了一个版本手动编译又装了一个版本那基本就是冲突了。解决办法有两种。第一种是统一版本把手动装的卸掉只用apt的版本或者反过来。第二种是让Caffe明确使用某个版本在Makefile.config里把PROTOBUF_INCLUDE和PROTOBUF_LIB指向你想要的版本路径。我个人的做法是编译Caffe之前先把系统里的protobuf清理干净然后手动编译安装一个2.6.1版本。虽然老但和Caffe的兼容性最好。安装步骤是下载源码、./configure、make、make install然后ldconfig刷新库缓存。4.2 OpenCV 4.x带来的接口不兼容如果你系统里装的是OpenCV 4.x编译Caffe时大概率会遇到CV_LOAD_IMAGE_COLOR未定义的错误。这个宏在OpenCV 4里被改成了cv::IMREAD_COLOR。Caffe的代码里用的是老写法所以编译不过。解决办法有两个一是降级到OpenCV 3.x二是手动改Caffe源码。我选的是后者因为降级OpenCV可能影响系统里其他依赖OpenCV的程序。具体改法是找到报错的文件通常是src/caffe/util/io.cpp和src/caffe/layers/image_data_layer.cpp把CV_LOAD_IMAGE_COLOR替换成cv::IMREAD_COLOR把CV_LOAD_IMAGE_GRAYSCALE替换成cv::IMREAD_GRAYSCALE。改完之后重新编译即可。这个坑的教训是Caffe的代码和现代库之间存在代沟遇到类似问题不要死磕要么降版本要么改代码两条路都能走通。4.3 链接阶段的未定义引用怎么定位链接错误比编译错误更难查因为报错信息往往是一大串符号名看不出是哪个库的问题。我的经验是从报错信息里找关键词。比如看到cblas_开头的符号说明BLAS库没链接上看到H5开头的说明HDF5没配好看到cv::开头的说明OpenCV路径有问题。定位到是哪个库之后回到Makefile.config检查对应的LIBRARY_DIRS和LDFLAGS。有时候库文件确实存在但名字不对比如你装的是libopenblas.so但Makefile里找的是libcblas.so那就需要建一个软链接或者改Makefile。还有一个隐蔽的情况库的架构不匹配。比如你的系统是64位的但某个库只有32位版本链接时就会报错。用file命令检查库文件的架构确认是ELF 64-bit。5. 环境跑通之后的一些实用建议5.1 把Caffe集成到你的工作流里编译完只是第一步真正用起来还需要一些配置。如果你用Python写脚本建议把Caffe的Python路径写进.bashrcexport CAFFE_ROOT/path/to/your/caffe export PYTHONPATH$CAFFE_ROOT/python:$PYTHONPATH export LD_LIBRARY_PATH$CAFFE_ROOT/build/lib:$LD_LIBRARY_PATH这样每次打开终端都自动生效不用手动export。注意LD_LIBRARY_PATH这一行很多人只配了PYTHONPATH结果运行时报找不到libcaffe.so就是漏了这个。如果你用CMake管理自己的项目可以在CMakeLists.txt里这样引用Caffefind_package(Caffe REQUIRED) include_directories(${Caffe_INCLUDE_DIRS}) target_link_libraries(your_project ${Caffe_LIBRARIES})前提是Caffe安装时生成了CaffeConfig.cmake如果没有就需要手动指定路径。5.2 模型转换与跨框架协作的现实问题现在纯用Caffe训新模型的人已经不多了更常见的场景是拿PyTorch训练好的模型转成Caffe格式去部署。这个转换过程有不少坑比如层类型对不上、参数命名不一致、某些算子Caffe不支持等。我的建议是转换之前先确认目标Caffe版本支持哪些层。Caffe的层类型是固定的那些PyTorch里一些新奇的算子比如各种注意力机制在Caffe里根本没有对应实现。遇到这种情况要么用Caffe的自定义层功能自己写要么换部署方案。转换工具方面有开源的pytorch2caffe之类的脚本但质量参差不齐很多只支持基本的卷积网络。我试过几个对ResNet这种标准结构还行稍微复杂一点的网络就各种报错。所以如果你的模型结构比较新做好手动改转换脚本的心理准备。5.3 关于Caffe是否还值得学的个人看法最后说点实在的。Caffe作为一个框架它的生命周期确实已经进入尾声了官方仓库好几年没更新了。但这不代表学它没意义。理解Caffe的架构设计对理解深度学习框架的演进很有帮助。它的prototxt定义网络的方式、blob作为数据载体的设计、layer作为计算单元的组织方式这些思想在后来的框架里都能看到影子。而且现实情况是很多工业项目还在用Caffe你接手了就得会。与其抱怨怎么还在用这老古董不如花半天时间把环境搭好把流程跑通。我自己的经验是Caffe环境搭一次之后后面换机器照着笔记走半小时就能搞定。真正花时间的是第一次踩坑的过程而这个过程一旦走完你对Linux编译、依赖管理、动态链接这些底层知识的理解会上一个台阶。如果你在搭建过程中遇到了本文没覆盖的报错我的建议是去翻Caffe的GitHub Issues里面几乎能找到所有常见问题的讨论。搜索的时候用报错信息里的关键词不要用整句话搜命中率更高。另外编译日志一定要保存下来make all 21 | tee build.log出问题的时候可以慢慢翻。