docker使用GPU總結


在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將其終止以釋放顯卡資源.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM