在Ubuntu 18.04上安装深度学习训练环境

By | May 5, 2020

0x00:前传
去年底又入了一台DELL,这次是因为需要GPU训模型,正好Nvidia出了基于Turing核心的GTX-1660Ti用于笔记本,比2060少了Tensor Core,但显存一样是6G,想想Tensor Core的意义在于FP16加速训练,但半精度训练配置比较繁琐,暂时不折腾也罢,于是6799入了这台Dell-G3-3590游戏本,被我装上Ubuntu训模型,训练速度比CPU快了20~30倍,大概有V100单卡的50%,而价格只及V100的1/10,非常适合用来学习。

第一次折腾CUDA,实现了CUDA9和CUDA10共存,能同时支持下面两个环境,把安装过程记录一下。
tensorflow-gpu 1.9:CUDA9 + cuDNN 7.0
darknet:CUDA10 + cuDNN 7.5

0x01:理论
CUDA分为两个部分,内核态的驱动(.ko)和用户态的动态链接库(.so)。CUDA的内核态驱动是高版本兼容低版本。而一般说的CUDA9或者CUDA10是指用户态动态链接库的版本,跨版本不兼容,因此,理论上只需要安装一个高版本的内核态驱动,然后通过将CUDA的用户态库安装到不同目录中来达到多版本共存目的。

内核态的驱动版本号一般是3xx.mm或4xx.mm,例如,现在最新的是440.64,在Ubuntu下,由nvidia-driver-4xx和它的依赖包提供。

用户态的动态链接库,其实是一系列的功能库组成的集合,例如cudart, cublas, curand, cufft等,由cuda-libraries-10-0和它的依赖包提供。

还有一个部分,是CUDA内核函数编译器(此内核并非操作系统内核,应该是源于filer的kernel概念,这里指运行在GPU中的算子),由cuda-compiler-10-0和它的依赖包提供。如果需要运行自定义的CUDA kernel函数,就需要安装这个包,例如编译darknet就需要它。

0x02:现状
Ubuntu有两个源提供CUDA驱动和库,一个是Ubuntu的官方源,另一个是Nvidia提供的源。Nvidia源比较新,并且提供了CUDA各个版本共存的机制,所以经过一番尝试后,最终选择了Nvidia源。

0x03:安装CUDA内核态的驱动和CUDA10
在新立得包管理器(synaptic)中,打开“设置”->“软件库”->“其他软件”,点击“添加”,分别添加下面两个Nvidia源,然后关闭并自动刷新:

1
2
deb http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64 /
deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 /

如果是手动编辑/etc/apt/source.list并遇到如下错误:

1
W: GPG error: https://developer.download.nvidia.cn/compute/machine-learning/repos/ubuntu1804/x86_64  Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY F60F4B3D7FA2AF80

可通过命令自动添加证书:

1
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F60F4B3D7FA2AF80

搜索cuda,找到下面两个包,分别点击右键选“标记安装”,将会自动标记所需依赖。

1
2
3
cuda-runtime-10-0
cuda-libraries-dev-10-0
cuda-compiler-10-0

点击“应用”,然后大概需要下载1G的内容,安装后占据2G空间。安装完后,在终端中运行nvidia-smi检查是否成功。如果提示未找到设备,可以尝试自己载入内核态驱动:

1
sudo modprobe nvidia-uvm

如果成功,将会显示如下的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Tue May  5 15:21:43 2020      
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 440.82       Driver Version: 440.82       CUDA Version: 10.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 166...  Off  | 00000000:01:00.0 Off |                  N/A |
| N/A   64C    P0     0W /  N/A |      0MiB /  5944MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

0x04:安装CUDA9
在新立得包管理器(synaptic)中,打开“设置”->“软件库”->“其他软件”,点击“添加”,分别添加下面两个Nvidia源(注意,这里添加的是16.04的源,只有这个源中才有CUDA9!!!)

1
2
deb http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1604/x86_64 /
deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64 /

关闭并自动刷新后,搜索cuda-libraries-9-0,右键选“标记安装”,将会自动标记所需依赖。

好了,现在两个版本的用户态库分别安装到这两个位置了:

1
2
/usr/local/cuda-9.0
/usr/local/cuda-10.0

0x05:安装cuDNN
cuDNN是CUDA的深度学习支持库,但是,不知道为啥,这个跨版本不兼容的库,Nvidia使用了版本兼容的语义进行安装,这会导致只能二选一的问题。
什么是跨版本兼容的语义呢?首先,包名中只有大版本:libcudnn7,第二,程序编译时,指向了只包含大版本号的符号链:/usr/lib/x86_64-linux-gnu/libcudnn.so.7。
遇上这样的情况:TF1.9依赖cuDNN 7.0版,而如果Darknet依赖cuDNN 7.5,就懵了。

解决方案其实很简单:搞清楚具体是哪一个.so,然后在运行程序时,通过环境变量LD_LIBRARY_PATH来控制加载哪一个。

方式一(命令行):

1
2
3
4
5
6
# 安装cuDNN 7.0
sudo apt install libcudnn7-dev=7.0.5.15-1+cuda9.0 libcudnn7=7.0.5.15-1+cuda9.0
# 备份cuDNN 7.0
sudo mv /usr/lib/x86_64-linux-gnu/libcudnn.so.7* /usr/local/cuda-9.0/lib64/
# 安装cuDNN 7.5
sudo apt install libcudnn7-dev=7.5.1.10-1+cuda10.0 libcudnn7=7.5.1.10-1+cuda10.0

方式二(新立得包管理器):
安装cuDNN 7.0
在新立得包管理器(synaptic)中,搜索libcudnn7,选中结果后,点击菜单“软件包”->“强制版本”,选择“7.0.xxx+cuda9.0 (developer.download.nvidia.com)”,确定、应用后,查看libcudnn7右键属性中的“已安装文件”我们发现cuDNN提供的.so库只有这一个:/usr/lib/x86_64-linux-gnu/libcudnn.so.7.0.5,然后有一个/usr/lib/x86_64-linux-gnu/libcudnn.so.7符号链指向了它。
我们在终端中,把这个版本复制到一个目录中,因为后面装7.5版的时候会被覆盖:

1
sudo mv /usr/lib/x86_64-linux-gnu/libcudnn.so.7* /usr/local/cuda-9.0/lib64/

安装cuDNN 7.5
在新立得包管理器(synaptic)中,搜索libcudnn7,对结果中的libcudnn7和libcudnn7-dev分别操作:点击菜单“软件包”->“强制版本”,选择“7.5.xxx+cuda10.0 (developer.download.nvidia.com)”,确定、应用后,系统的cuDNN已经被覆盖为7.5版本了。

这里,我们用7.5版本作为默认安装,也就是说,不改变任何环境变量,默认加载的cuDNN是7.5版本。如果需要7.0版本,那么就通过在命令前增加赋值来启动:

1
LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64/:$LD_LIBRARY_PATH python3 train.py

0x06:清理
刚刚,为了安装CUDA9.0,我们添加了Ubuntu 16.04的Nvidia源,这个源中的CUDA10以及更新的包其实是不兼容Ubuntu 18.04的,为了以后不出现误操作,我们把这个源禁用掉:在新立得包管理器(synaptic)中,打开“设置”->“软件库”->“其他软件”,找到两个包含ubuntu1604的源,去掉前面的钩就行啦!

0x07:安装tensorflow, pytorch, darknet …
后一篇文章《训练一个跑在嵌入式环境的YOLOv4模型检测人,猫,狗》介绍了基于Darknet进行YOLOv4检测模型的训练,至于tensorflow、pytorch介绍的文章很多了,基本都是常规操作,就不多说了~

Category: AI

Leave a Reply

Your email address will not be published. Required fields are marked *