0%

Docker使用手记(2) 构建一个MXNET开发镜像

  1. 直接安装MXNET的Docker镜像
  2. 安装Ubuntu镜像
  3. 安装CUDA + cuDNN
    1. 查看操作系统
    2. 第一次安装失败
    3. 使用gpus标志
    4. 再次安装CUDA
  4. Python安装mxnet gpu
  5. 制作镜像

首先创建一个容器,安装python、CUDA、cuDNN、mxnet等工具后成功跑通后,再将构建命令写入到Dockerfile中,构建镜像。

操作系统:Windows11 22000.318

Docker版本:v20.10.11

直接安装MXNET的Docker镜像

https://hub.docker.com/r/mxnet/python/tags

装的是这个版本:1.5.0_gpu_cu101_py3_ub18

好不容易装好之后,运行

1
2
3
docker run -it --name py --gpus all mxnet/python:1.5.0_gpu_cu101_py3_ub18 bash
python3
import mxnet

结果给我提示

1
libgomp.so.1: cannot open shared object file: No such file or directory

解决:apt-get update && apt-get install libgomp1

或者使用另一个镜像:1.5.0_gpu_cu101mkl_py3_ub18

1
docker pull mxnet/python:1.5.0_gpu_cu101mkl_py3_ub18

安装完镜像之后还需要用到gluoncv,将其写到RUN命令中保存为Dockerfile文件,交由VS Code使用。

这是使用tag==1.5.0_gpu_cu101_py3_ub18的Dockerfile:

1
2
3
FROM mxnet/python:1.5.0_gpu_cu101mkl_py3_ub18

RUN pip3 install gluoncv

这是使用tag==1.5.0_gpu_cu101mkl_py3_ub18的Dockerfile:

1
2
3
4
5
FROM mxnet/python:1.5.0_gpu_cu101_py3_ub18

RUN apt-get update \
&& apt-get install libgomp1 \
&& pip3 install gluoncv

直接安装镜像取得了成功,下面的内容就当瞎折腾吧


安装Ubuntu镜像

拉取镜像

1
docker pull ubuntu:18.04

构建容器

1
docker run -dit --name py ubuntu:18.04

进入容器

1
docker exec -it py bash

安装CUDA + cuDNN

查看操作系统

1
2
3
4
5
6
7
8
9
10
11
12
13
cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.6 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.6 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

第一次安装失败

安装CUDA Toolkit

1
2
3
4
apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
echo "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 /" > /etc/apt/sources.list.d/cuda.list
apt-get update
apt-get install -y cuda-toolkit-10-1

测试CUDA

1
2
3
cd /usr/local/cuda/samples/4_Finance/BlackScholes
make
./BlackScholes

测试失败,提示错误:code=35(cudaErrorInsufficientDriver)

看人家测试成功的是在微软商店安装的Ubuntu下装的CUDA,我用的是docker镜像ubuntu:18.04,上面这个错误的原因是“已安装的NVIDIA CUDA驱动版本低于CUDA运行库”,是因为镜像中没有CUDA驱动,考虑往镜像中安装驱动。

使用gpus标志

Docker 19.3之后的版本整合了nvidia,在docker run提供了一个标志位--gpus,可以向容器中传递NVIDIA GPU。API参考

并且WSL2中也支持了GPU。WSL 2 GPU Support is Here

因此,只要通过如下命令,就可以把系统的驱动传递到容器中

1
docker run -it --rm --gpus all ubuntu:18.04 nvidia-smi

但是执行以上命令的时候,遇到了以下错误:

1
Stderr: nvidia-container-cli: initialization error: driver error: failed to process request: unknown

折腾了一番只找到Linux下的解决方案,有几个完美解决的NVIDIA/nvidia-docker/issues/726记一次 nvidia docker 错误追查,但都是Linux下的。

1
sudo apt-get remove nvidia-384 ; sudo apt-get install nvidia-384

虽然不是我想要的,但是简单记录一下。大致意思就是说Linux系统的NVIDIA驱动没装好,重新装一下缺失的组件就可以了。和Windows相关的解决方案也十分离谱,关键词Windows,Docker,GPU,WSL,出来的结果的预设条件都是这样的:微软商店下载一个Ubuntu,在这个Ubuntu上安装NVIDIA驱动,然后把驱动传递到装在这个Ubuntu上面的Docker容器里边去(???),然后解决方案和上述Linux的一毛一样😡。而我想做的是,在Windows安装的Docker中,将Windows的NVIDIA驱动传递到容器里面,真是牛头不对马嘴!

继续折腾的时候发现了这么一个东西:CUDA on Windows Subsystem for Linux (WSL),下下来一看是一个Windows驱动程序安装包,恍然大悟或许这就是我想要的东西,之前传递不进去会不会就是没有安装对驱动,这么一安装说不定就成了!果然,安装成功后,不报上面的错误了。

遇到另一个问题:

1
2
NVIDIA-SMI couldn't find libnvidia-ml.so library in your system. Please make sure that the NVIDIA Display Driver is properly installed and present in your system.
Please also try adding directory that contains libnvidia-ml.so to your system PATH.

大致意思是在ubuntu系统下执行nvidia-smi命令时,找不到运行库libnvidia-ml.so,至少说明,NVIDIA驱动传入到容器中了,完成一小步。

再次安装CUDA

NVIDIA提供了一个关于如何在WSL2上构建GPU应用的文档:https://docs.nvidia.com/cuda/wsl-user-guide/index.html#ch03a-setting-up-cuda

有两种安装CUDA的方法:

第一种:使用WSL-Ubuntu包

1
2
3
4
5
6
7
wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin
sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/11.4.0/local_installers/cuda-repo-wsl-ubuntu-11-4-local_11.4.0-1_amd64.deb
sudo dpkg -i cuda-repo-wsl-ubuntu-11-4-local_11.4.0-1_amd64.deb
sudo apt-key add /var/cuda-repo-wsl-ubuntu-11-4-local/7fa2af80.pub
sudo apt-get update
sudo apt-get -y install cuda

第二种:使用元数据包。元数据包不包含驱动,只会安装CUDA工具集。

1
2
3
4
5
6
7
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-ubuntu2004.pin
sudo mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/11.4.0/local_installers/cuda-repo-ubuntu2004-11-4-local_11.4.0-470.42.01-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu2004-11-4-local_11.4.0-470.42.01-1_amd64.deb
sudo apt-key add /var/cuda-repo-ubuntu2004-11-4-local/7fa2af80.pub
sudo apt-get update
sudo apt-get install -y cuda-toolkit-11-4

第一次安装使用的方法类似于这边的第二种。这边尝试使用WSL-Ubuntu包安装,这一过程的历史命令如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$apt-get update
$apt-get install wget # 安装网络下载工具
$cd home;mkdir download;cd download
$wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin
$mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600
$wget https://developer.download.nvidia.com/compute/cuda/11.4.0/local_installers/cuda-repo-wsl-ubuntu-11-4-local_11.4.0-1_amd64.deb
$dpkg -i cuda-repo-wsl-ubuntu-11-4-local_11.4.0-1_amd64.deb # 提示失败,要在apt-key中添加东西
$apt-key add /var/cuda-repo-wsl-ubuntu-11-4-local/7fa2af80.pub # 提示失败,要安装gpupg
$apt-get install gnupg # apt-key add 需要用到gnupg
$apt-key add /var/cuda-repo-wsl-ubuntu-11-4-local/7fa2af80.pub
$dpkg -i cuda-repo-wsl-ubuntu-11-4-local_11.4.0-1_amd64.deb
$apt-get update
$apt-get -y install cuda

$nvidia-smi # 查看驱动信息
$/usr/local/cuda-11.4/bin/nvcc -V # 查看toolkit信息

安装成功后跑一个测试

1
2
3
cd /usr/local/cuda-11.4/samples/4_Finance/BlackScholes
make
./BlackScholes

若一切都顺利,则出现类似如下的输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[./BlackScholes] - Starting...
GPU Device 0: "Pascal" with compute capability 6.1

Initializing data...
...allocating CPU memory for options.
...allocating GPU memory for options.
...generating input data in CPU mem.
...copying input data to GPU mem.
Data init done.

Executing Black-Scholes GPU kernel (512 iterations)...
Options count : 8000000
BlackScholesGPU() time : 0.654793 msec
Effective memory bandwidth: 122.176023 GB/s
Gigaoptions per second : 12.217602

BlackScholes, Throughput = 12.2176 GOptions/s, Time = 0.00065 s, Size = 8000000 options, NumDevsUsed = 1, Workgroup = 128

Reading back GPU results...
Checking the results...
...running CPU calculations.

Comparing the results...
L1 norm: 1.741792E-07
Max absolute error: 1.192093E-05

Shutting down...
...releasing GPU memory.
...releasing CPU memory.
Shutdown done.

[BlackScholes] - Test Summary

NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled.

Test passed

WSL-Ubuntu包提供的CUDA版本都是大于11的,教程安装的是CUDA 11.4,虽然预期使用的CUDA版本是10.1,但先忽略这个问题,继续向后安装,如果出问题了再换成10.1的。

Python安装mxnet gpu

使用python:slim镜像,在这个镜像上按照上节方式安装CUDA之后,安装mxnet

设置pip国内镜像源:

1
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

安装mxnet并测试

1
2
3
pip install mxnet-cu101
python
import mxnet

出现错误

1
OSError: libcudart.so.10.1: cannot open shared object file: No such file or directory

看来还是需要安装一个10.1版本的CUDA。。。对上面那个CUDA 10.1安装的方式做了点修改,把http改成https,能对下载速度有所提升(之前要下好几个小时)

1
2
3
4
apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
echo "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 /" > /etc/apt/sources.list.d/cuda.list
apt-get update
apt-get install -y cuda-toolkit-10-1

然后安装完提示新的错误:

1
OSError: libcublas.so.10: cannot open shared object file: No such file or directory

这个文件明明存在的……

1
2
3
find | grep libcublas.so.10
# ./usr/local/cuda-10.2/targets/x86_64-linux/lib/libcublas.so.10.2.3.254
# ./usr/local/cuda-10.2/targets/x86_64-linux/lib/libcublas.so.10

算了,重新装吧。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@2e7946c6e5a7:/# history
1 python -V
2 pip -V
3 apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
# ↑ 提示需要安装 gnupg
4 apt-get update
5 apt-get install gnupg
6 apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
7 echo "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 /" > /etc/apt/sources.list.d/cuda.list
8 apt-get update
9 apt-get install -y cuda-toolkit-10-1
10 nvidia-smi
11 nvcc
12 find | grep nvcc
13 ./usr/local/cuda-10.1/bin/nvcc -V #

16 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
# Writing to /root/.config/pip/pip.conf
17 pip install mxnet-cu101==1.5.1 # 别忘了指定版本号,太高的版本可能不适配

测试

1
2
3
python
import mxnet
# libcudnn.so.7: cannot open shared object file: No such file or directory

好,接下来就是cuDNN了!它的安装过程比较简单,就是安装包的获取比较艰难,需要登录后下载,下载后还不好搞到镜像里头,后来是在Windows下面搭了个静态服务器,在容器中用wget下载的,简单记录下操作历史:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
38  wget http://127.0.0.1:8888/cudnn-10.1-linux-x64-v7.6.5.32.tgz
39 tar -zxvf cudnn-10.1-linux-x64-v7.6.5.32.tgz # 解压
40 cp cuda/include/cudnn /usr/local/cuda-10.1/include/ # 复制文件
41 cp cuda/include/cudnn.h /usr/local/cuda-10.1/include/
42 cp cuda/lib64/libcudnn* /usr/local/cuda-10.1/lib64/
43 chmod a+r /usr/local/cuda-10.1/include/cudnn.h # 设置权限
44 chmod a+r /usr/local/cuda-10.1/lib64/libcudnn*
50 apt-get install nano
# 设置环境变量
51 nano ~/.bashrc
export CUDA_HOME=/usr/local/cuda-10.1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CUDA_HOME/lib64
export PATH=$PATH:$CUDA_HOME/bin
54 source ~/.bashrc # 应用设置

制作镜像

CUDA Toolkit Archive

cuDNN Archive

制作镜像的思路是:把CUDA和cuDNN下载下来放在上下文中,然后通过执行一连串的安装命令构建镜像。但是构建的时候一直失败,也不知道是处理逻辑出错了还是咋地。。总之暂时失败了以及发现mxnet提供的容器似乎是能用起来的,就先不考虑自己折腾了,上面的折腾过程就当是在Ubuntu下安装CUDA和cuDNN的教程吧。

最后附一下构建失败的Dockerfile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
FROM python:slim

COPY cuda/* /home/download/

ENV CUDA_HOME=/usr/local/cuda-10.1

ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CUDA_HOME/lib64

ENV PATH=$PATH:$CUDA_HOME/bin

RUN apt-get update \
&& apt-get install -y gnupg \
&& cd /home/download \
&& mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600 \
&& dpkg -i cuda-repo-ubuntu1804-10-1-local-10.1.243-418.87.00_1.0-1_amd64.deb \
&& apt-key add /var/cuda-repo-10-1-local-10.1.243-418.87.00/7fa2af80.pub \
&& apt-get update && apt-get -y install cuda \
&& tar -zxvf cudnn-10.1-linux-x64-v7.6.5.32.tgz \
&& cp cuda/include/cudnn /usr/local/cuda-10.1/include/ \
&& cp cuda/include/cudnn.h /usr/local/cuda-10.1/include/ \
&& cp cuda/lib64/libcudnn* /usr/local/cuda-10.1/lib64/ \
&& chmod a+r /usr/local/cuda-10.1/include/cudnn.h \
&& chmod a+r /usr/local/cuda-10.1/lib64/libcudnn* \
&& source ~/.bashrc \
&& pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple \
&& pip install mxnet-cu101==1.5.1