在osx上编译,首先需要了解一些常识和掌握一些基本技能。
- 基本编译工具是xcode自带的clang。默认没有gcc。
- xcode 7 对应MacOSX10.11.sdk,xcode 8 对应MacOSX10.12.sdk。当本文后面需要设置sdk路径的时候,确保版本正确(后面的路径默认用的是10.11)。
- 会使用homebrew安装软件包。
- 会使用cmake和make编译软件包。
- 如果需要python接口,熟悉osx python路径和包安装。
- 如果需要matlab接口,熟悉matlab路径和mex。
caffe项目对OSX的适配不太好,编译过程可能很曲折,要有心理准备。
1. 环境准备
首先,确保安装好了XCode 7或者XCode 8和最新的CUDA SDK,测试nvcc确保可以正常使用。
2. 安装依赖包
根据官网教程,安装依赖包:
brew install snappy leveldb gflags glog szip lmdb
brew tap homebrew/science
brew install hdf5 opencv
brew install --build-from-source --with-python -vd protobuf
brew install --build-from-source -vd boost boost-python
brew install protobuf boost
安装依赖包有两点注意事项:
+ 其中opencv体积较大,可以下载源码编译安装。安装好依赖后,从github下载caffe源码,准备开始编译。
+ 其中leveldb需要从github上下载源码编译安装。
make
sudo cp -r out-shared/* /usr/local/lib
sudo cp -r out-static/* /usr/local/lib
否则之后caffe运行会报错:
caffe(2446,0x7fffab4003c0) malloc: *** malloc_zone_unregister() failed for 0x7fffab3f6000
这个错误虽然不会使caffe立即崩溃,但会导致caffe非常不稳定。
3. 编译OpenCV
在CMakeLists.txt中添加
include_directories(/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include)
否则会找不到 string.h。
3.1 OpenCV 3.0 兼容性
编译OpenCV 3.0时可能遇到QTKit.h找不到的错误,cmake时添加一个参数,即
cmake -DBUILD_opencv_videoio=OFF
OpenCV3删除了highgui模块,替代的是imgcodecs和vidoeio模块。在caffe编译中,如果遇到highgui找不到的错误,修改include 为
// #include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
另外修改imread函数中得第二个参数CV_LOAD_IMAGE_COLOR为
cv::IMREAD_COLOR
将CV_LOAD_IMAGE_GRAYSCALE修改为
cv::IMREAD_GRAYSCALE
3.2 OpenCV lib替换Matlab的Opencv lib
在编译 matlab接口前,将/usr/local/lib下的libopencv复制到 ${MATLAB_ROOT}/bin/maci64 下覆盖matlab自带的opencvlib,或者直接删除${MATLAB_ROOT}/bin/maci64 下的libopencv*.dylib。否则编译虽然能成功,Matlab接口运行时会出现 “找不到opencv imread 符号”的错误。
4. 编译CUDA加速的caffe
4.1 常见的编译错误及解决方法
在osx上编译caffe会遇到一些错误,其中最主要的问题是caffe不能正确识别osx10.12上自带的blas库,也就是 Accelerate / vecLib。
首先,打开终端,切换到源码根目录,执行
mkdir build
cd build
cmake ..
- 报找不到vecLib错误。解决方法:修改cmake/Modules/FindvecLib.cmake文件
# Find the vecLib libraries as part of Accelerate.framework or as standalon framework
#
# The following are set after configuration is done:
# VECLIB_FOUND
# vecLib_INCLUDE_DIR
# vecLib_LINKER_LIBS
if(NOT APPLE)
return()
endif()
SET(vecLib_INCLUDE_SEARCH_PATHS
/System/Library/Frameworks/vecLib.framework/Versions/Current/Headers/
/System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/Versions/Current/Headers/
)
FIND_PATH(vecLib_INCLUDE_DIR NAMES cblas.h PATHS ${vecLib_INCLUDE_SEARCH_PATHS})
FIND_LIBRARY(vecLib_LIBRARY Accelerate)
SET(vecLib_FOUND ON)
MARK_AS_ADVANCED(
vecLib_INCLUDE_DIR
vecLib_LIBRARY
vecLib
)
if(VECLIB_FOUND)
if(vecLib_INCLUDE_DIR MATCHES "^/System/Library/Frameworks/vecLib.framework.*")
set(vecLib_LINKER_LIBS -lcblas "-framework vecLib")
message(STATUS "Found standalone vecLib.framework")
else()
set(vecLib_LINKER_LIBS -lcblas "-framework Accelerate")
message(STATUS "Found vecLib as part of Accelerate.framework")
endif()
mark_as_advanced(vecLib_INCLUDE_DIR)
endif()
另一种方法是使用openblas。修改 cmake/modules/FindvecLib.cmake中的path最后一行为
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Accelerate.framework/Versions/Current/Frameworks/vecLib.framework/Headers/
还有一种临时解决方法:打开build目录下的CmakeCaches.txt,修改
vecLib_INCLUDE_DIR:PATH=
将其后面的内容替换为
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/Headers/
注意10.11是对应xcode7,如果你用xcode8,应该写成10.12。另外还需要注意你的nvcc是不是兼容xcode8。Nvidia官网最新的nvcc已经支持xcode8.0了。
重新cmake,会报找不到 Accelerate/accelerate.h错误。
- 找不到Accelerate/Accelerate.h。解决方法:不用自带的blas (accelerate.framework / vecLib),用openblas。
首先,下载安装gcc和Openblas。直接用brew安装编译会出错,因此只能下载openblas源码编译。而编译openblas又需要gcc和gfortran。故而:
下载 gcc-x.x.x-bin.tar.gz,解压到/usr/local目录。
下载 openblas源码并编译安装到/usr/local目录:
make
make PREFIX=/usr/local install
注意,不要用cmake编译openblas,会出错。直接在根目录下make就可以了。
然后,本应该修改Cmake.config,修改blas选项为openblas,即
BLAS := open
BLAS_INCLUDE := /usr/local/include
BLAS_LIB := /usr/local/lib
但测试发现选项没有生效。于是直接打开根目录Makefile,修改blas configuration一节为
# BLAS configuration (default = ATLAS)
#BLAS ?= atlas
BLAS := open
ifeq ($(BLAS), mkl)
# MKL
LIBRARIES += mkl_rt
COMMON_FLAGS += -DUSE_MKL
MKL_DIR ?= /opt/intel/mkl
BLAS_INCLUDE ?= $(MKL_DIR)/include
BLAS_LIB ?= $(MKL_DIR)/lib $(MKL_DIR)/lib/intel64
else
# # ifeq ($(BLAS), open)
# OpenBLAS
LIBRARIES += openblas
#else
# ATLAS
# ifeq ($(LINUX), 1)
# ifeq ($(BLAS), atlas)
# Linux simply has cblas and atlas
# LIBRARIES += cblas atlas
# endif
# else ifeq ($(OSX), 1)
# OS X packages atlas as the vecLib framework
# LIBRARIES += cblas
# 10.10 has accelerate while 10.9 has veclib
# XCODE_CLT_VER := $(shell pkgutil --pkg-info=com.apple.pkg.CLTools_Executables | grep 'version' | sed 's/[^0-9]*\([0-9]\).*/\1/')
# ifeq ($(XCODE_CLT_GEQ_6), 1)
# BLAS_INCLUDE ?= /System/Library/Frameworks/Accelerate.framework/Versions/Current/Frameworks/vecLib.framework/Headers/
# LDFLAGS += -framework Accelerate
# else
# BLAS_INCLUDE ?= /System/Library/Frameworks/vecLib.framework/Versions/Current/Headers/
# LDFLAGS += -framework vecLib
# endif
# endif
endif
强制使用openblas。再次编译。
- 找不到string.h等。解决方法:修改根目录下CMakeLists.txt,添加
include_directories(/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include)
之后再
cmake ..
make
make install
一切顺利。
添加动态链接库路径
运行caffe,会发现找不到一些动态链接库。于是修改/etc/profile文件,添加
export DYLD_FALLBACK_LIBRARY_PATH=/usr/local/cuda/lib:/usr/local/lib:$DYLD_FALLBACK_LIBRARY_PATH
在终端中执行
source /etc/profile
使修改生效。之后运行caffe,一切正常。
4.2 python接口的配置
在import caffe时,会报出一些依赖路径的问题。
添加python的caffe路径
export PYTHONPATH=/Users/tomheaven/Documents/caffe-master/python
设置DYLD_FALLBACK_LIBRARY_PATH
export DYLD_FALLBACK_LIBRARY_PATH=/Developer/NVIDIA/CUDA-8.0/lib:/usr/local:/usr/local/cuda/lib:/usr/local/lib:$DYLD_FALLBACK_LIBRARY_PATH
安装依赖
# 解决找不到 protobuf
sudo chmod -R a+rw /Library/Python/2.7/site-packages/
pip install protobuf
# 解决找不到 dot
brew install graphviz
4.3 编译matlab接口
在Makefile.config中,修改
MATLAB_DIR := /Applications/MATLAB_R2014b.app
添加
LIBRARY_DIRS += /Applications/MATLAB_R2014b.app/bin/maci64
修改cmake命令为
cmake -DBUILD_matlab=ON ..
重新编译
会遇到-lpython2 找不到的问题。这时修改 build/matlab/cmake/matlab.dir/build.cmake中的-lpython2为-lpython2.7
在build.cmake的/Applications/MATLAB_R2014b.app/bin/mex最前面添加
-L/Applications/MATLAB_R2014b.app/bin/maci64
否则会找不到libmx.dylib和libmex.dylib,报出一大堆mx打头的链接错误。
运行matcaffe样例时,还会遇到libcurand等dylib无法找到的问题,需要在${MATLAB_ROOT}/bin/maci64/目录下创建软链接:
sudo ln -s /Developer/NVIDIA/CUDA-8.0/lib/libcurand.8.0.dylib /Applications/MATLAB_R2014b.app/bin/maci64/
sudo ln -s /Developer/NVIDIA/CUDA-8.0/lib/libcudart.8.0.dylib /Applications/MATLAB_R2014b.app/bin/maci64/
sudo ln -s /Developer/NVIDIA/CUDA-8.0/lib/libcublas.8.0.dylib /Applications/MATLAB_R2014b.app/bin/maci64/
运行Matlab测试的时候,caffe.Solver会导致Matlab崩溃,目前未找到解决办法。其他测试通过。
4.4 不用CUDA的编译方法
cmake -DCPU_ONLY=ON ..
make
可以成功编译没有CUDA支持的caffe。
5. 总结
也许将来caffe项目会改进对于osx的支持,但截至2016.11.30,编译还是会遇到许多问题。总结起来如下:
- caffe需要blas才能编译成功。默认的atlas是使用osx上的accelerate framework的vecLib。但实际编译时无法找到或者正常编译完成,因此需要修改FindvecLib.cmake或者选择用openblas替代。
- 其他错误只需修复对应的目录即可。主要是/usr/local/include,/usr/lib/,/usr/local/lib和CUDA目录。
- XCode的Framekworks常用目录:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks
- 不要安装第三方python或者多个版本python。OSX python默认路径
/System/Library/Frameworks/Python.framework/Versions/Current
site-packages默认路径
/Library/Python/2.7/site-packages
- Matlab接口虽然可以编译出来,但是运行Caffe.Solver会导致Matlab崩溃,目前无解。