在docker容器中使用顯卡
一 docker19.03以前的事情
1.1 指定顯卡硬件名
最初的容器中使用顯卡,需要指定硬件名。經歷了兩種方式
1. 使用lxc驅動程序運行docker守護進程,以便能夠修改配置並讓容器訪問顯卡設備(非常麻煩,參考鏈接中最久遠的回答)
2. Docker 0.9中放棄了lxc作為默認執行上下文,但是依然需要指定顯卡的名字
(1)找到你的顯卡設備
ls -la /dev | grep nvidia
crw-rw-rw- 1 root root 195, 0 Oct 25 19:37 nvidia0
crw-rw-rw- 1 root root 195, 255 Oct 25 19:37 nvidiactl
crw-rw-rw- 1 root root 251, 0 Oct 25 19:37 nvidia-uvm
(2)啟動容器時,指定顯卡設備
sudo docker run -ti --device /dev/nvidia0:/dev/nvidia0 --device /dev/nvidiactl:/dev/nvidiactl --device /dev/nvidia-uvm:/dev/nvidia-uvm tleyden5iwx/ubuntu-cuda /bin/bash
1.2 nvidia-docker
英偉達公司開發了nvidia-docker,該軟件是對docker的包裝,使得容器能夠看到並使用宿主機的nvidia顯卡.
本質上,他們找到了一種方法來避免在容器中安裝CUDA/GPU驅動程序,並讓它與主機內核模塊匹配。 
測試:
# Install nvidia-docker and nvidia-docker-plugin wget -P /tmp https://github.com/NVIDIA/nvidia-docker/releases/download/v1.0.1/nvidia-docker_1.0.1-1_amd64.deb sudo dpkg -i /tmp/nvidia-docker*.deb && rm /tmp/nvidia-docker*.deb # Test nvidia-smi nvidia-docker run --rm nvidia/cuda nvidia-smi
指定使用兩張卡:
docker run --rm --gpus 2 nvidia/cuda nvidia-smi
更詳細得得用法見:User Guide — NVIDIA Cloud Native Technologies documentation
另外要注意nvidia-docker包括nvidia-docker1 和 nvidia-docker2,兩者命令有一定差異
二 docker 19.03
感覺docker已是toB公司的必備吧,有了docker再也不用擔心因客戶環境問題導致程序各種bug,也大大省去了配置客戶服務器的過程。
很多機器學習項目要使用GPU,所以需要docker支持GPU,在docker19以前的版本都需要單獨下載nvidia-docker1或nvidia-docker2來啟動容器,自從升級了docker19后跑需要gpu的docker只需要加個參數–gpus all 即可(表示使用所有的gpu,如果要使用2個gpu:–gpus 2,也可直接指定哪幾個卡:–gpus ‘“device=1,2”’,后面有詳細介紹)。
接着需要安裝nvidia驅動,這需要根據自己顯卡安裝相應的驅動,網上有很多類似教程,此處不再介紹。
不要以為這樣就可以安心的使用gpu了,你的鏡像還必須要有cuda才行,這也很簡單,去dockerhub上找到和自己tensorflow相對應的cuda版本的鏡像,再基於該鏡像生成自己的鏡像就可以輕松使用gpu了。這里需要額外多說一句,如果你的docker 本身就基於了某個鏡像(例如基於本公司倉庫的鏡像),docker是不允許from兩個鏡像的,要想實現基於兩個或多個,只能基於其中一個,其他的鏡像通過各鏡像的Dockerfile拼到新的Dockerfile上,但更多的鏡像是沒有Dockerfile的,可以通過docker history查看某鏡像的生成過程,其實就是Dockerfile,nvidia/cuda官網本身就有Dockerfile,也可直接參考。
小結:要想在容器內使用gpu,每一層需要做好的事情
1、k8s:需要安裝nvidia-device-plugin支持gpu調度。 詳見https://www.cnblogs.com/linhaifeng/p/16111733.html
2、容器內:需要有cuda庫
3、docker:安裝docker19.03,低於此版本需要額外安裝插件
4、操作系統:安裝cuda驅動程序
5、硬件:插入gpu卡
2.1 安裝toolkit
關於配置docker19使用gpu,其實只用裝官方提供的toolkit即可,把github上的搬下來:
Ubuntu 16.04/18.04, Debian Jessie/Stretch/Buster:
# Add the package repositories $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list $ sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit $ sudo systemctl restart docker
CentOS 7 (docker-ce), RHEL 7.4/7.5 (docker-ce), Amazon Linux 1/2
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | sudo tee /etc/yum.repos.d/nvidia-docker.repo $ sudo yum install -y nvidia-container-toolkit $ sudo systemctl restart docker
2.2 測試安裝是否成功
經過以上大部分linux系統的docker toolkit應該都能安裝成功,如不能安裝成功,可參考github官網,查看是否安裝成功:
(1) 查看–gpus 參數是否安裝成功:
$ docker run --help | grep -i gpus --gpus gpu-request GPU devices to add to the container ('all' to pass all GPUs)
(2) 運行nvidia官網提供的鏡像,並輸入nvidia-smi命令,查看nvidia界面是否能夠啟動:
docker run --gpus all nvidia/cuda:9.0-base nvidia-smi
2.3 運行gpu的容器
從Docker 19.03開始,安裝好docker之后,只需要使用 --gpus 即可指定容器使用顯卡。
所有顯卡都對容器可見: docker run --gpus all --name 容器名 -d -t 鏡像id 只有顯卡1對容器可見: docker run --gpus="1" --name 容器名 -d -t 鏡像id 如果不指定 --gpus ,運行nvidia-smi 會提示Command not found
注意:
1. 顯卡驅動在所有方式中,都要先安裝好,容器是不會有顯卡驅動的,一台物理機的顯卡只對應一個顯卡驅動,當顯卡驅動安裝好后(即使未安裝cuda),也可以使用命令nvidia-smi
2. nvidia-smi顯示的是顯卡驅動對應的cuda版本,nvcc -V 顯示的運行是cuda的版本
補充
啟動容器時,容器如果想使用gpu,鏡像里必須有cuda環境,就是說,針對想使用gpu的容器,鏡像在制作時必須吧cuda環境打進去 --gpus '"device=1,2"',這個的意思是,將物理機的第二塊、第三塊gpu卡映射給容器? 下面三個參數代表的都是是容器內可以使用物理機的所有gpu卡 --gpus all NVIDIA_VISIBLE_DEVICES=all --runtime=nvida NVIDIA_VISIBLE_DEVICES=2 只公開兩個gpu,容器內只能用兩個gpu
舉例如下:
# 使用所有GPU $ docker run --gpus all nvidia/cuda:9.0-base nvidia-smi # 使用兩個GPU $ docker run --gpus 2 nvidia/cuda:9.0-base nvidia-smi # 指定GPU運行 $ docker run --gpus '"device=1,2"' nvidia/cuda:9.0-base nvidia-smi $ docker run --gpus '"device=UUID-ABCDEF,1"' nvidia/cuda:9.0-base nvidia-smi
ok,可以開心愉快的使用gpu了!!
后續
參考資料:
https://blog.csdn.net/qq_33547243/article/details/107433616
https://www.cnblogs.com/shoufu/p/12904832.html
https://github.com/NVIDIA/nvidia-docker/issues/533
首先介紹幾個事實:
1. 最初的docker是不支持gpu的
2. 為了讓docker支持nvidia顯卡,英偉達公司開發了nvidia-docker。該軟件是對docker的包裝,使得容器能夠看到並使用宿主機的nvidia顯卡。
3. 根據網上的資料,從docker 19版本之后,nvidia-docker成為了過去式。不需要單獨去下nvidia-docker這個獨立的docker應用程序,只需要安裝並配置一下nvidia-runtime,使用的時候用--gpus參數來控制。
(P.S.:因為本實驗室服務器的docker默認是支持nvidia的runtime的,所以我在這里沒有過多糾結,讀者假如從零開始安裝docker軟件的話可能要細心地保證docker是支持gpu的docker)
然后我做了幾個有代表性的實驗:
1. docker run 的時候不加 --gpus參數,典型代碼:
docker run -it --name test --rm ubuntu:latest
此時在容器內運行nvidia-smi會提示Command not found
2. docker run 的時候加上 --gpus參數,典型代碼:
docker run -it --rm --name test --gpus all ubuntu:latest
此時在容器內運行nvidia-smi會有如下輸出:
從這兩個實驗我們可以得出結論,docker在啟動容器的時候添加的--gpus參數確實是給容器添加了新東西的。比如/usr/bin/nvidia-smi這個可執行程序,如果你不添加--gpus參數是不會給你放到容器中的!此外可以推測,不加--gpus參數,宿主的gpu將對於容器不可見。
還有一個需要注意的點是nvidia-smi的輸出!CUDA Version: N/A
首先,我的宿主機的CUDA是明確的11.0版本,宿主機的nvidia driver是明確的450.57版本(這一點宿主和容器一致)。那么為什么這里顯示 N/A 呢?
抱着nvidia-smi能用driver一定沒問題的想法,我三下五除二地在docker中安裝了pytorch。可是運行測試代碼的時候傻眼了,測試代碼:
import torch torch.cuda.is_available()
輸出報錯結果如下:
UserWarning: CUDA initialization: Found no NVIDIA driver on your system. Please check that you have an NVIDIA GPU and installed a driver from http://www.nvidia.com/Download/index.aspx (Triggered internally at /pytorch/c10/cuda/CUDAFunctions.cpp:100.)
return torch._C._cuda_getDeviceCount() > 0
為什么Pytorch找不到NVIDIA driver?? 我的driver哪里有問題?? nvidia-smi不是運行的好好的??
嘗試過在docker內重裝多版本的cuda無果,嘗試在docker內重裝nvidia驅動反而導致nvidia-smi都無法運行。直到我在參考資料3中找到了解決方案,原來是環境變量的問題。
最后,拉一個GPU docker的正確姿勢:
docker run -itd --gpus all --name 容器名 -e NVIDIA_DRIVER_CAPABILITIES=compute,utility -e NVIDIA_VISIBLE_DEVICES=all 鏡像名
多出來的東西其實就是這個家伙:NVIDIA_DRIVER_CAPABILITIES=compute,utility
也就是說,如果你不改這個環境變量,宿主機的nvidia driver在容器內是僅作為utility存在的,如果加上compute,宿主機的英偉達driver將對容器提供計算支持(所謂的計算支持也就是cuda支持)。
docker exec進入容器,再次運行nvidia-smi
和宿主機的輸出就完全相同了。
再次嘗試pytorch的測試代碼,輸出為True。
至此,你就獲得了一個具有nvidia driver和cuda支持的docker。(需要注意的是,我的pytorch是直接用conda安裝的,它的依賴cudatoolkits僅對conda可見,如果你需要cuda做更多事,可能還需要進一步的嘗試。但是我猜想既然nvidia-smi的輸出是好的,那么大概率沒問題)
問題:容器內執行nvidia-smi不顯示pid
解決方法:
# 安裝包 apt-get install psmisc # 用這條命令進行查看 fuser -v /dev/nvidia*
注:本方法針對docker不顯示pid而選擇的另外一種間接查看方法
可以利用sudo kill -9 pid將其終止以釋放顯卡資源.
