前两天,一个师弟问了一个问题,“当电脑里面有多个cudnn的时候,caffe如何使用不同版本的cudnn?”然后还发了下面的链接给我: link。
我觉得这一份笔记写的已经很清楚,但是在路径方面有一点小错误,所以我重新整理了一下,在加上自己的一些理解。
下面先讲怎么处理多个cudnn。
从
/usr/local/cuda
目录下移除cudnn相关的文件(这一步其实不是必须的,因为后面的两个步骤3-4的操作会使新版本的cudnn的优先级高于原有的版本),操作如下:sudo rm /usr/local/cuda/lib64/libcudnn* sudo rm /usr/local/cuda/include/cudnn.h
- 新建一个目录集中管理各个版本的cudnn库,比如~/cudnn/cudnn_v5存放第五版,~/cudnn/cudnn_v6存放第六版;
- 修改caffe根目录下的Makefile.config的
INCLUDE_DIRS
,添加对应版本的cudnn的include目录,添加lib64目录到LIBRARY_DIRS
(通过这一步修改之后,在编译caffe的过程中已经能成功找到对应的头文件和静态库); 修改.bashrc文件或者.profile文件末尾,添加对应版本cudnn目录下的lib64到
LD_LIBRARY_PATH
(这一步是为了让caffe的程序在运行的过程中,注意是运行而非编译,找到对应的cudnn动态库):export LD_LIBRARY_PATH=/home/XXX/cudnn/cudnn_v6/lib64:$LD_LIBRARY_PATH
PS:如果对.bashrc文件或者.profile文件不清楚的,可以参考下面的链接: link
到这里,就讲完了~~下面是我自己的一些理解,可以直接忽略~
cudnn(The NVIDIA CUDA® Deep Neural Network library):是一个深度神经网络加速库。一般下载解压之后会有include
和lib64
两个文件夹,分别存放的时候头文件(.h
)和库文件(包括静态库.a
和动态库.so
文件)。
要成功使用cudnn版本的caffe,需要有下面的三个因素:
- 告诉caffe头文件(
.h
)在哪里。这一步是通过赋值cudnn的include文件的路径给Makefile
文件中的INCLUDE_DIRS
变量实现的; - 告诉caffe静态链接库(
.a
)在哪里。这一步是通过赋值cudnn的lib64文件的路径给Makefile
文件中的LIBRARY_DIRS
变量实现的; 告诉caffe动态链接库(
.so
)在哪里。这一步是通过给环境变量LD_LIBRARY_PATH
添加cudnn的lib64文件的路径来实现的。PS:因素1-2影响到是否能正常编译caffe源码,因素3则影响到caffe能否正常运行(当然都是在需要cudnn加速的情况下),所以想让caffe使用某一个版本的cudnn,只需要让caffe最先找到该版本的对应文件。
一般配caffe在cudnn的部分是进行了下面的操作:
会把include和lib64中的文件复制到cuda相应的文件夹下面,一般是:
$ cd cudnn/cudnn_v5/lib64/
$ sudo cp lib* /usr/local/cuda/lib64/
$ cd ..
$ cd include
$ sudo cp cudnn.h /usr/local/cuda/include/
这样做的目的是确保编译caffe的时候能找到cudnn相关的头文件和库文件,大致过程如下:
caffe根目录下的Makefile.config文件中有:
CUDA_DIR := /usr/local/cuda
caffe的根目录下的Makefile文件中有:
CUDA_INCLUDE_DIR := $(CUDA_DIR)/include CUDA_LIB_DIR := # add <cuda>/lib64 only if it exists ifneq ("$(wildcard $(CUDA_DIR)/lib64)","") CUDA_LIB_DIR += $(CUDA_DIR)/lib64 endif CUDA_LIB_DIR += $(CUDA_DIR)/lib INCLUDE_DIRS += $(BUILD_INCLUDE_DIR) ./src ./include ifneq ($(CPU_ONLY), 1) INCLUDE_DIRS += $(CUDA_INCLUDE_DIR) LIBRARY_DIRS += $(CUDA_LIB_DIR) LIBRARIES := cudart cublas curand endif
所以在执行caffe中的Makefile文件的时候,会把
/usr/local/cuda/include/
和/usr/local/cuda/lib64/
赋值给INCLUDE_DIRS
和LIBRARY_DIRS
,这样编译caffe的时候就能找到cudnn相关的文件。再加上装cuda的时候,一般会在系统或者用户自己的.profile
或者.bashrc
文件中加上:export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
这样,运行caffe的时候就能找到对应的cudnn动态库了。
之所以可以跳过步骤1(不删除/usr/local/cuda
下旧版cudnn的先关文件),是因为:
按照步骤2-4添加新的cudnn的路径之后,新版本的cudnn使用时候的优先级高于原有的版本:
在Makefile文件中执行:
INCLUDE_DIRS += $(CUDA_INCLUDE_DIR) LIBRARY_DIRS += $(CUDA_LIB_DIR)
的时候,
INCLUDE_DIRS
和LIBRARY_DIRS
经过Makefile.config的赋值,已经包含了新版的cudnn的include和lib64路径,所以优先级高于旧版本cudnn所在的/usr/local/cuda/include/
和/usr/local/cuda/lib64/
,所以编译caffe的源文件的时候首选的是新版的cudnn的头文件和静态链接库;在步骤4修改.bashrc文件或者.profile文件:
export LD_LIBRARY_PATH=/home/XXX/cudnn/cudnn_v6/lib64:$LD_LIBRARY_PATH
之后,新版的cudnn的lib64路径在
LD_LIBRARY_PATH
中位于旧版的/usr/local/cuda/lib64/
的前面(可以通过echo $LD_LIBRARY_PATH
看看),所以运行caffe的可执行文件的时候首选的是新版的cudnn的动态链接库。
大概就是这些了~希望能帮助到有需要的朋友。