GPU aus einem Docker-Container verwenden?

164

Ich suche nach einer Möglichkeit, die GPU in einem Docker-Container zu verwenden.

Der Container führt beliebigen Code aus, sodass ich den privilegierten Modus nicht verwenden möchte.

Irgendwelche Tipps?

Aus früheren Untersuchungen habe ich verstanden, dass run -vund / oder LXC cgroupder richtige Weg war, aber ich bin mir nicht sicher, wie ich das genau durchziehen soll

Regan
quelle
Siehe stackoverflow.com/questions/17792161/…, das Ihren Anforderungen entspricht.
Nicolas Goy
1
@NicolasGoy Der Link war gut, aber nicht so nützlich, da ich aus Sicherheitsgründen keine privilegierten verwenden kann. Die lxc-cgroups waren ein guter Zeiger, aber nicht genug. Ich habe einen Weg gefunden und werde selbst antworten, wenn alles poliert ist.
Regan

Antworten:

132

Regans Antwort ist großartig, aber etwas veraltet, da der richtige Weg, dies zu tun, darin besteht, den lxc-Ausführungskontext zu vermeiden, da Docker LXC ab Docker 0.9 als Standardausführungskontext gelöscht hat .

Stattdessen ist es besser, Docker über das Flag --device über die nvidia-Geräte zu informieren und statt lxc nur den nativen Ausführungskontext zu verwenden.

Umgebung

Diese Anweisungen wurden in der folgenden Umgebung getestet:

  • Ubuntu 14.04
  • CUDA 6.5
  • AWS GPU-Instanz.

Installieren Sie den nvidia-Treiber und cuda auf Ihrem Host

Informationen zum Einrichten Ihres Host-Computers finden Sie in CUDA 6.5 auf der AWS GPU-Instanz unter Ubuntu 14.04 .

Installieren Sie Docker

$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
$ sudo sh -c "echo deb https://get.docker.com/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
$ sudo apt-get update && sudo apt-get install lxc-docker

Finden Sie Ihre NVIDIA-Geräte

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

Führen Sie den Docker-Container mit vorinstalliertem NVIDIA-Treiber aus

Ich habe ein Docker-Image erstellt , auf dem die Cuda-Treiber vorinstalliert sind. Die Docker-Datei ist auf Dockerhub verfügbar, wenn Sie wissen möchten, wie dieses Image erstellt wurde.

Sie sollten diesen Befehl an Ihre NVIDIA-Geräte anpassen. Folgendes hat bei mir funktioniert:

 $ 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

Stellen Sie sicher, dass CUDA korrekt installiert ist

Dies sollte in dem Docker-Container ausgeführt werden, den Sie gerade gestartet haben.

Installieren Sie CUDA-Beispiele:

$ cd /opt/nvidia_installers
$ ./cuda-samples-linux-6.5.14-18745345.run -noprompt -cudaprefix=/usr/local/cuda-6.5/

Beispiel für die Erstellung von deviceQuery:

$ cd /usr/local/cuda/samples/1_Utilities/deviceQuery
$ make
$ ./deviceQuery   

Wenn alles funktioniert hat, sollten Sie die folgende Ausgabe sehen:

deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 6.5, CUDA Runtime Version = 6.5, NumDevs =    1, Device0 = GRID K520
Result = PASS
tleyden
quelle
3
Warum installieren Sie lxc-docker, wenn Sie dann lxc nicht benötigen?
MP0
4
Ich habe CUDA 5.5 auf dem Host und CUDA 6.5 in einem Container, der aus Ihrem Image erstellt wurde. CUDA arbeitet auf dem Host und ich habe die Geräte an den Container übergeben. Der Container sieht die GPUs durch, ls -la /dev | grep nvidiaaber CUDA kann kein CUDA-fähiges Gerät finden: ./deviceQuery ./deviceQuery Starting... CUDA Device Query (Runtime API) version (CUDART static linking) cudaGetDeviceCount returned 38 -> no CUDA-capable device is detected Result = FAIL Liegt es an der Nichtübereinstimmung der CUDA-Bibliotheken auf dem Host und im Container?
Brunetto
1
Ich weiß nicht, vielleicht möchten Sie in den NVIDIA-Foren nachfragen. Angenommen, die Versionsinkongruenz ist ein Problem, können Sie diese Docker-Datei nehmen und bearbeiten, um die CUDA 5.5-Treiber zu erhalten. Erstellen Sie dann ein neues Docker-Image daraus und verwenden Sie diese.
Tleyden
3
Können Sie erklären, warum das Image den NVIDIA-Treiber installieren muss? Ich dachte nur Host zu installieren nvidia Treiber (und verwenden --device ...) ist ausreichend?
Helin Wang
2
Derzeit gibt es keine Möglichkeit, dies zu tun, wenn Sie Windows als Host haben.
Souradeep Nanda
45

Schreiben einer aktualisierten Antwort, da die meisten der bereits vorhandenen Antworten ab sofort veraltet sind.

Versionen früher als Docker 19.03früher erforderlich nvidia-docker2und das --runtime=nvidiaFlag.

Seitdem Docker 19.03müssen Sie das nvidia-container-toolkitPaket installieren und dann das --gpus allFlag verwenden.

Also, hier sind die Grundlagen,

Paketinstallation

Installieren Sie das nvidia-container-toolkitPaket gemäß der offiziellen Dokumentation bei Github .

Führen Sie für Redhat-basierte Betriebssysteme die folgenden Befehle aus:

$ 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

Führen Sie für Debian-basierte Betriebssysteme die folgenden Befehle aus:

# 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

Ausführen des Dockers mit GPU-Unterstützung

docker run --name my_all_gpu_container --gpus all -t nvidia/cuda

Bitte beachten Sie, dass das Flag --gpus allverwendet wird, um alle verfügbaren GPus dem Docker-Container zuzuweisen.

So weisen Sie dem Docker-Container eine bestimmte GPU zu (falls mehrere GPUs auf Ihrem Computer verfügbar sind)

docker run --name my_first_gpu_container --gpus device=0 nvidia/cuda

Oder

docker run --name my_first_gpu_container --gpus '"device=0"' nvidia/cuda
Rohit
quelle
5
Ab 2019 ist dies die richtige Art, GPU aus Docker-Containern heraus zu verwenden.
Timur Bakeyev
1
Hat jemand dies jemals in einem Batch-Job bei AWS versucht?
medley56
1
Ich glaube, das ist am relevantesten. Ich wünschte, ich hätte es früher gefunden, obwohl ich die Anweisungen von github.com/NVIDIA/nvidia-docker anpassen musste, um mit Ubuntu
20.04
40

Ok, ich habe es endlich geschafft, ohne den --privileged-Modus zu verwenden.

Ich laufe auf Ubuntu Server 14.04 und verwende das neueste Cuda (6.0.37 für Linux 13.04 64 Bit).


Vorbereitung

Installieren Sie den nvidia-Treiber und cuda auf Ihrem Host. (Es kann etwas schwierig sein, daher empfehle ich Ihnen, diesem Handbuch zu folgen. /ubuntu/451672/installing-and-testing-cuda-in-ubuntu-14-04 )

ACHTUNG: Es ist sehr wichtig, dass Sie die Dateien behalten, die Sie für die Installation des Host-Cuda verwendet haben


Lassen Sie den Docker-Daemon mit lxc ausführen

Wir müssen den Docker-Daemon mit dem lxc-Treiber ausführen, um die Konfiguration ändern und dem Container Zugriff auf das Gerät gewähren zu können.

Einmalige Nutzung:

sudo service docker stop
sudo docker -d -e lxc

Permanente Konfiguration Ändern Sie Ihre Docker-Konfigurationsdatei in / etc / default / docker. Ändern Sie die Zeile DOCKER_OPTS, indem Sie '-e lxc' hinzufügen. Hier ist meine Zeile nach der Änderung

DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4 -e lxc"

Starten Sie dann den Daemon mit neu

sudo service docker restart

Wie kann ich überprüfen, ob der Dämon den lxc-Treiber effektiv verwendet?

docker info

Die Zeile "Ausführungstreiber" sollte folgendermaßen aussehen:

Execution Driver: lxc-1.0.5

Erstellen Sie Ihr Image mit dem NVIDIA- und CUDA-Treiber.

Hier ist eine grundlegende Docker-Datei zum Erstellen eines CUDA-kompatiblen Images.

FROM ubuntu:14.04
MAINTAINER Regan <http://stackoverflow.com/questions/25185405/using-gpu-from-a-docker-container>

RUN apt-get update && apt-get install -y build-essential
RUN apt-get --purge remove -y nvidia*

ADD ./Downloads/nvidia_installers /tmp/nvidia                             > Get the install files you used to install CUDA and the NVIDIA drivers on your host
RUN /tmp/nvidia/NVIDIA-Linux-x86_64-331.62.run -s -N --no-kernel-module   > Install the driver.
RUN rm -rf /tmp/selfgz7                                                   > For some reason the driver installer left temp files when used during a docker build (i don't have any explanation why) and the CUDA installer will fail if there still there so we delete them.
RUN /tmp/nvidia/cuda-linux64-rel-6.0.37-18176142.run -noprompt            > CUDA driver installer.
RUN /tmp/nvidia/cuda-samples-linux-6.0.37-18176142.run -noprompt -cudaprefix=/usr/local/cuda-6.0   > CUDA samples comment if you don't want them.
RUN export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64         > Add CUDA library into your PATH
RUN touch /etc/ld.so.conf.d/cuda.conf                                     > Update the ld.so.conf.d directory
RUN rm -rf /temp/*  > Delete installer files.

Führen Sie Ihr Bild aus.

Zuerst müssen Sie die Hauptnummer identifizieren, die Ihrem Gerät zugeordnet ist. Am einfachsten ist es, den folgenden Befehl auszuführen:

ls -la /dev | grep nvidia

Wenn das Ergebnis leer ist, sollten Sie das Starten eines der Beispiele auf dem Host verwenden, um den Trick auszuführen. Das Ergebnis sollte so aussehen. Geben Sie hier die Bildbeschreibung ein Wie Sie sehen, gibt es zwischen der Gruppe und dem Datum einen Satz von 2 Zahlen. Diese beiden Zahlen werden als Haupt- und Nebenzahlen bezeichnet (in dieser Reihenfolge geschrieben) und entwerfen ein Gerät. Wir werden der Einfachheit halber nur die Hauptzahlen verwenden.

Warum haben wir den lxc-Treiber aktiviert? Verwendung der Option lxc conf, mit der wir unserem Container den Zugriff auf diese Geräte ermöglichen können. Die Option ist: (Ich empfehle die Verwendung von * für die untergeordnete Zahl, da dies die Länge des Ausführungsbefehls verringert.)

--lxc-conf = 'lxc.cgroup.devices.allow = c [Hauptnummer]: [Nebennummer oder *] rwm'

Also, wenn ich einen Container starten möchte (Angenommen, Ihr Bildname ist cuda).

docker run -ti --lxc-conf='lxc.cgroup.devices.allow = c 195:* rwm' --lxc-conf='lxc.cgroup.devices.allow = c 243:* rwm' cuda
Regan
quelle
Können Sie den Container teilen?
ChillarAnand
1
Docker bietet die --deviceOption, dem Container den Zugriff auf das Gerät des Hosts zu ermöglichen. Ich habe jedoch versucht, --device=/dev/nvidia0Docker-Container zuzulassen, um cuda auszuführen, und bin fehlgeschlagen.
Shiquanwang
4
Es gelang mir dann mit allen auszusetzen /dev/nvidiao, /dev/nvidia1, /dev/nvidiactlund /dev/nvidia-uvmmit --device. Obwohl ich nicht weiß warum.
Shiquanwang
Die Option --device wurde nicht implementiert, als ich diese Lösung finden musste. Sie benötigen mindestens nvidia0 oder nvidia1 (Grafikkarte) und nvidiactl (allgemeines nvidia-Gerät) und nvidia-uvm (United-Speichergerät).
Regan
2
Vielen Dank für Ihre Hinweise zum /dev/nvidia*@Regan. Für @ChillarAnand habe ich einen Cuda-Docker gemacht
Shiquanwang
29

Wir haben gerade ein experimentelles GitHub-Repository veröffentlicht, das die Verwendung von NVIDIA-GPUs in Docker-Containern vereinfachen soll.

3XX0
quelle
4
Gibt es Windows-Unterstützung? Es scheint nicht so zu sein, aber vielleicht fehlt mir etwas.
Blaze
6
Es gibt keine Windows-Unterstützung. Zum Ausführen des CUDA-Containers sind Nvidia-Treiber für Linux und der Zugriff auf Linux-Geräte erforderlich, die die GPU darstellen, z. B. / dev / nvidia0. Diese Geräte und Treiber sind nicht verfügbar, wenn Docker unter Windows installiert ist und in der virtuellen VirtualBox-Maschine ausgeführt wird.
Paweł Bylica
Benötigen Sie noch die --device-Deklarationen im Befehl run? Ich habe einen Container FROM nvidia / cuda erstellt und der Container läuft einwandfrei, aber die App (Wowza) erkennt die GPUs nicht, während es gut funktioniert, wenn es direkt auf dem Host ausgeführt wird (dieser Host, also weiß ich, dass Treiber in Ordnung sind). . Ich laufe 361.28. Der Host ist EC2 mit NVidia AMI auf g2.8xlarge.
rainabba
Nein, alles wird von nvidia-
docker erledigt.
22

Die jüngsten Verbesserungen von NVIDIA haben zu einer wesentlich robusteren Methode geführt.

Im Wesentlichen haben sie einen Weg gefunden, um zu vermeiden, dass der CUDA / GPU-Treiber in den Containern installiert werden muss und mit dem Host-Kernel-Modul übereinstimmt.

Stattdessen befinden sich Treiber auf dem Host und die Container benötigen sie nicht. Es erfordert derzeit eine modifizierte Docker-Cli.

Das ist großartig, denn jetzt sind Container viel tragbarer.

Geben Sie hier die Bildbeschreibung ein

Ein kurzer Test unter Ubuntu:

# 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

Weitere Informationen finden Sie unter: GPU-fähiger Docker-Container und: https://github.com/NVIDIA/nvidia-docker

Matt
quelle
Dies funktioniert gut, wenn Sie alle Schritte erhalten haben. Nvidia bietet nicht alles an einem Ort, aber dieses Beispiel bietet alles, was Sie benötigen, damit es mit einem allgemeinen Anwendungsfall funktioniert.
KobeJohn
@KobeJohn - Ich habe gerade die Installationsanweisungen und die Verwendung der Befehlszeile befolgt und sichergestellt, dass meine Container von den Cuda-Containern erben. Es funktioniert nur bei mir.
Matt
1
Können Sie tatsächlich die realen Szenarien angeben, in denen die Verwendung von nvidia-docker sinnvoll ist?
Suncatcher
@Suncatcher - Ich verwende es in einem Cluster, der für das 3D-Rendering Zugriff auf die GPU benötigt. Durch das Andocken der Apps wurde die Bereitstellung und Wartung vereinfacht.
Matt
17

Aktualisiert für cuda-8.0 auf Ubuntu 16.04

Dockerfile

FROM ubuntu:16.04
MAINTAINER Jonathan Kosgei <jonathan@saharacluster.com>

# A docker container with the Nvidia kernel module and CUDA drivers installed

ENV CUDA_RUN https://developer.nvidia.com/compute/cuda/8.0/prod/local_installers/cuda_8.0.44_linux-run

RUN apt-get update && apt-get install -q -y \
  wget \
  module-init-tools \
  build-essential 

RUN cd /opt && \
  wget $CUDA_RUN && \
  chmod +x cuda_8.0.44_linux-run && \
  mkdir nvidia_installers && \
  ./cuda_8.0.44_linux-run -extract=`pwd`/nvidia_installers && \
  cd nvidia_installers && \
  ./NVIDIA-Linux-x86_64-367.48.run -s -N --no-kernel-module

RUN cd /opt/nvidia_installers && \
  ./cuda-linux64-rel-8.0.44-21122537.run -noprompt

# Ensure the CUDA libs and binaries are in the correct environment variables
ENV LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda-8.0/lib64
ENV PATH=$PATH:/usr/local/cuda-8.0/bin

RUN cd /opt/nvidia_installers &&\
    ./cuda-samples-linux-8.0.44-21122537.run -noprompt -cudaprefix=/usr/local/cuda-8.0 &&\
    cd /usr/local/cuda/samples/1_Utilities/deviceQuery &&\ 
    make

WORKDIR /usr/local/cuda/samples/1_Utilities/deviceQuery
  1. Führen Sie Ihren Container aus

sudo docker run -ti --device /dev/nvidia0:/dev/nvidia0 --device /dev/nvidiactl:/dev/nvidiactl --device /dev/nvidia-uvm:/dev/nvidia-uvm <built-image> ./deviceQuery

Sie sollten eine Ausgabe ähnlich der folgenden sehen:

deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 8.0, CUDA Runtime Version = 8.0, NumDevs = 1, Device0 = GRID K520 Result = PASS

Jonathan
quelle
3
Ich bekomme folgende Ausgabe. cudaGetDeviceCount zurückgegeben 38 -> kein CUDA-fähiges Gerät erkannt Ergebnis = FAIL
Soichi Hayashi
Späte Antwort, aber es bedeutet, dass Sie wahrscheinlich keine GPU auf diesem Computer haben
Jonathan
Wäre eine Cuda-9-Version fast dieselbe?
Huseyin Tugrul Buyukisik
@huseyintugrulbuyukisik siehe diese Antwort auf askubuntu askubuntu.com/questions/967332/… . Ich würde sagen, Sie könnten diese Antwort als Leitfaden verwenden, aber ich habe nicht mit cuda 9 gearbeitet, um zu bestätigen, dass dieselben Schritte gelten würden
Jonathan
Mach es nicht so. Das ist der alte Weg. Verwenden Sie den neuen Weg. Siehe Link zu meiner Antwort. Diese Methode ist mit Problemen behaftet.
Matt
3

Verwenden Sie Nvidia-Docker, um die GPU aus dem Docker-Container zu verwenden, anstatt den nativen Docker zu verwenden. Verwenden Sie die folgenden Befehle, um Nvidia Docker zu installieren

curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey |  sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/ubuntu16.04/amd64/nvidia-
docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update
sudo apt-get install -y nvidia-docker
sudo pkill -SIGHUP dockerd # Restart Docker Engine
sudo nvidia-docker run --rm nvidia/cuda nvidia-smi # finally run nvidia-smi in the same container
Patel Sunil
quelle
1

Verwenden Sie x11docker von mviereck:

https://github.com/mviereck/x11docker#hardware-acceleration sagt

Hardware-Beschleunigung

Die Hardwarebeschleunigung für OpenGL ist mit den Optionen -g, --gpu möglich.

Dies funktioniert in den meisten Fällen sofort mit Open Source-Treibern auf dem Host. Ansonsten schauen Sie sich das Wiki an: Feature-Abhängigkeiten. NVIDIA-Treiber mit geschlossener Quelle benötigen einige Einstellungen und unterstützen weniger x11docker X-Serveroptionen.

Dieses Skript ist sehr praktisch, da es die gesamte Konfiguration und Einrichtung übernimmt. Das Ausführen eines Docker-Images auf X mit GPU ist so einfach wie

x11docker --gpu imagename
phil294
quelle