¿Usando GPU de un contenedor acoplable?

164

Estoy buscando una manera de usar la GPU desde el interior de un contenedor acoplable.

El contenedor ejecutará código arbitrario, así que no quiero usar el modo privilegiado.

¿Algun consejo?

De investigaciones anteriores, entendí que run -vy / o LXC cgroupera el camino a seguir, pero no estoy seguro de cómo lograrlo exactamente

Regan
fuente
Consulte stackoverflow.com/questions/17792161/… que es similar a su necesidad.
Nicolas Goy
1
@NicolasGoy El enlace era bueno pero no tan útil ya que no puedo usar privilegiado por razones de seguridad. El lxc-cgroups fue un buen puntero, pero no lo suficiente. Encontré un camino, y responderé cuando todo esté pulido.
Regan

Respuestas:

132

La respuesta de Regan es excelente, pero está un poco desactualizada, ya que la forma correcta de hacerlo es evitar el contexto de ejecución lxc ya que Docker ha eliminado LXC como contexto de ejecución predeterminado a partir de docker 0.9.

En cambio, es mejor decirle a Docker sobre los dispositivos nvidia a través del indicador --device, y simplemente usar el contexto de ejecución nativo en lugar de lxc.

Ambiente

Estas instrucciones se probaron en el siguiente entorno:

  • Ubuntu 14.04
  • CUDA 6.5
  • AWS GPU instancia.

Instale el controlador nvidia y cuda en su host

Consulte CUDA 6.5 en la instancia de GPU de AWS que ejecuta Ubuntu 14.04 para obtener la configuración de su máquina host.

Instalar 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

Encuentra tus dispositivos nvidia

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

Ejecute el contenedor Docker con el controlador nvidia preinstalado

He creado una imagen de Docker que tiene los controladores de Cuda preinstalados. El dockerfile está disponible en dockerhub si desea saber cómo se construyó esta imagen.

Querrá personalizar este comando para que coincida con sus dispositivos nvidia. Esto es lo que funcionó para mí:

 $ 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

Verifique que CUDA esté instalado correctamente

Esto debe ejecutarse desde el interior del contenedor acoplable que acaba de iniciar.

Instalar muestras de CUDA:

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

Construir dispositivo Ejemplo de consulta:

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

Si todo funcionó, debería ver el siguiente resultado:

deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 6.5, CUDA Runtime Version = 6.5, NumDevs =    1, Device0 = GRID K520
Result = PASS
Tleyden
fuente
3
¿Por qué instala lxc-docker si no necesita lxc entonces?
MP0
44
Tengo CUDA 5.5 en el host y CUDA 6.5 en un contenedor creado a partir de su imagen. CUDA está trabajando en el host y pasé los dispositivos al contenedor. El contenedor ve las GPU, ls -la /dev | grep nvidiapero CUDA no puede encontrar ningún dispositivo compatible con CUDA: ./deviceQuery ./deviceQuery Starting... CUDA Device Query (Runtime API) version (CUDART static linking) cudaGetDeviceCount returned 38 -> no CUDA-capable device is detected Result = FAIL ¿se debe a la falta de coincidencia de las bibliotecas CUDA en el host y en el contenedor?
brunetto
1
No sé, es posible que desee preguntar en los foros de nvidia. Suponiendo que la versión no coincida es un problema, puede tomar este Dockerfile y editarlo para que tenga los controladores CUDA 5.5, luego reconstruir una nueva imagen del docker y usarlo.
tleyden
3
¿Puede explicar por qué la imagen necesita instalar el controlador nvidia? Pensé que solo el host que instala el controlador nvidia (y el uso --device ...) es suficiente
Helin Wang
2
Actualmente no hay forma de hacerlo si tiene Windows como host.
Souradeep Nanda
46

Escribir una respuesta actualizada ya que la mayoría de las respuestas ya presentes son obsoletas a partir de ahora.

Versiones anteriores a las que Docker 19.03solía requerir nvidia-docker2y la --runtime=nvidiabandera.

Desde entonces Docker 19.03, debe instalar el nvidia-container-toolkitpaquete y luego usar la --gpus allbandera.

Entonces, aquí están los conceptos básicos,

Instalación de paquete

Instale el nvidia-container-toolkitpaquete según la documentación oficial en Github .

Para sistemas operativos basados ​​en Redhat, ejecute el siguiente conjunto de comandos:

$ 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

Para sistemas operativos basados ​​en Debian, ejecute el siguiente conjunto de comandos:

# 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

Ejecutar la ventana acoplable con soporte para GPU

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

Tenga en cuenta que la bandera --gpus allse usa para asignar todos los gpus disponibles al contenedor acoplable.

Para asignar una GPU específica al contenedor acoplable (en caso de múltiples GPU disponibles en su máquina)

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

O

docker run --name my_first_gpu_container --gpus '"device=0"' nvidia/cuda
Rohit
fuente
55
A partir de 2019, esta es la forma correcta de usar la GPU desde los contenedores acoplables.
Timur Bakeyev
1
¿Alguien ha intentado esto desde dentro de un trabajo Batch en AWS?
medley56
1
Creo que esto es lo más relevante. Ojalá lo hubiera encontrado antes, aunque tuve que adaptar las instrucciones de github.com/NVIDIA/nvidia-docker para trabajar con Ubuntu 20.04
VictorLegros
40

Ok, finalmente logré hacerlo sin usar el modo privilegiado.

Estoy corriendo en el servidor ubuntu 14.04 y estoy usando la última versión de cuda (6.0.37 para linux 13.04 64 bits).


Preparación

Instale el controlador nvidia y cuda en su host. (puede ser un poco complicado, así que te sugiero que sigas esta guía /ubuntu/451672/installing-and-testing-cuda-in-ubuntu-14-04 )

ATENCIÓN: es muy importante que conserve los archivos que usó para la instalación del host cuda


Haz que Docker Daemon se ejecute usando lxc

Necesitamos ejecutar docker daemon usando el controlador lxc para poder modificar la configuración y dar acceso al contenedor al dispositivo.

Utilización única:

sudo service docker stop
sudo docker -d -e lxc

Configuración permanente Modifique su archivo de configuración de docker ubicado en / etc / default / docker Cambie la línea DOCKER_OPTS agregando '-e lxc' Aquí está mi línea después de la modificación

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

Luego reinicia el demonio usando

sudo service docker restart

¿Cómo verificar si el demonio usa efectivamente el controlador lxc?

docker info

La línea del controlador de ejecución debería verse así:

Execution Driver: lxc-1.0.5

Cree su imagen con el controlador NVIDIA y CUDA.

Aquí hay un Dockerfile básico para construir una imagen compatible con CUDA.

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.

Ejecuta tu imagen.

Primero debe identificar su número principal asociado con su dispositivo. La forma más fácil es hacer el siguiente comando:

ls -la /dev | grep nvidia

Si el resultado está en blanco, el uso de iniciar una de las muestras en el host debería ser el truco. El resultado debería verse así. ingrese la descripción de la imagen aquí Como puede ver, hay un conjunto de 2 números entre el grupo y la fecha. Estos 2 números se llaman números mayores y menores (escritos en ese orden) y diseñan un dispositivo. Solo usaremos los números principales por conveniencia.

¿Por qué activamos el controlador lxc? Usar la opción lxc conf que nos permite permitir que nuestro contenedor acceda a esos dispositivos. La opción es: (recomiendo usar * para el número menor porque reduce la longitud del comando de ejecución)

--lxc-conf = 'lxc.cgroup.devices.allow = c [número mayor]: [número menor o *] rwm'

Entonces, si quiero iniciar un contenedor (suponiendo que el nombre de su imagen sea cuda).

docker run -ti --lxc-conf='lxc.cgroup.devices.allow = c 195:* rwm' --lxc-conf='lxc.cgroup.devices.allow = c 243:* rwm' cuda
Regan
fuente
¿Puedes compartir el contenedor?
ChillarAnand
1
Docker tiene una --deviceopción para permitir que el contenedor acceda al dispositivo del host. Sin embargo, traté de usar --device=/dev/nvidia0para permitir que el contenedor Docker ejecute cuda y fallé.
shiquanwang
44
Entonces tuve éxito con la exposición de todo /dev/nvidiao, /dev/nvidia1, /dev/nvidiactly /dev/nvidia-uvmcon --device. Aunque no sé por qué.
shiquanwang
La opción --device no se implementó cuando tuve que encontrar esta solución. Necesita al menos nvidia0 o nvidia1 (tarjeta gráfica) y nvidiactl (dispositivo nvidia general) y nvidia-uvm (dispositivo de memoria United).
Regan
2
Gracias por tus sugerencias sobre /dev/nvidia*@Regan. Para @ChillarAnand he hecho un cuda-docker
shiquanwang
29

Acabamos de lanzar un repositorio experimental de GitHub que debería facilitar el proceso de uso de GPU NVIDIA dentro de los contenedores Docker.

3XX0
fuente
44
¿Hay soporte para Windows? No parece ser, pero tal vez me estoy perdiendo algo.
Blaze
66
No hay soporte de Windows. La ejecución del contenedor CUDA requiere controladores Nvidia para Linux y acceso a dispositivos Linux que representan GPU, por ejemplo / dev / nvidia0. Estos dispositivos y controladores no están disponibles cuando Docker está instalado en Windows y se ejecuta dentro de la máquina virtual VirtualBox.
Paweł Bylica
¿Todavía necesita las declaraciones --device en el comando de ejecución? He creado un contenedor DESDE nvidia / cuda y el contenedor funciona bien, pero la aplicación (Wowza) no reconoce las GPU mientras funciona bien cuando se ejecuta directamente en el host (este host, así que sé que los controladores están bien) . Estoy corriendo 361.28. El host es EC2 usando NVidia AMI en g2.8xlarge.
rainabba
Nvidia-docker no se encarga de todo, debería poder ejecutar nvidia-smi dentro del contenedor y ver sus dispositivos
3XX0
22

Las mejoras recientes de NVIDIA han producido una forma mucho más sólida de hacer esto.

Esencialmente, han encontrado una manera de evitar la necesidad de instalar el controlador CUDA / GPU dentro de los contenedores y hacer que coincida con el módulo del núcleo del host.

En cambio, los controladores están en el host y los contenedores no los necesitan. Requiere un docker-cli modificado en este momento.

Esto es genial, porque ahora los contenedores son mucho más portátiles.

ingrese la descripción de la imagen aquí

Una prueba rápida en 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

Para obtener más detalles, consulte: Contenedor Docker habilitado para GPU y: https://github.com/NVIDIA/nvidia-docker

Mate
fuente
Esto funciona bien una vez que obtienes todos los pasos. Nvidia no lo proporciona todo en un solo lugar, pero este ejemplo le brinda todo lo que necesita para que funcione con un caso de uso común.
KobeJohn
@ KobeJohn: acabo de seguir las instrucciones de instalación, cómo usar la línea de comandos y asegurarme de que mis contenedores hereden de los de Cuda. Simplemente funciona para mí.
Matt
1
En realidad, ¿puedes dar los escenarios de la vida real donde el uso de nvidia-docker tiene sentido?
Suncatcher
@Suncatcher: lo estoy usando en un clúster que requiere acceso a la GPU para renderizar en 3D. Dockerizar las aplicaciones simplificó la implementación y el mantenimiento de las cosas.
Matt
17

Actualizado para cuda-8.0 en 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. Ejecute su contenedor

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

Debería ver una salida similar a:

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

Jonathan
fuente
3
Me sale el siguiente resultado. cudaGetDeviceCount devolvió 38 -> no se detectó ningún dispositivo con capacidad CUDA Resultado = FALLO
Soichi Hayashi
Respuesta tardía, pero significa que probablemente no tenga una GPU en esa máquina
Jonathan
¿Sería una versión de Cuda-9 casi igual que esta?
huseyin tugrul buyukisik
@huseyintugrulbuyukisik vea esta respuesta en askubuntu askubuntu.com/questions/967332/… , diría que podría usar esta respuesta como guía, pero no he trabajado con cuda 9 para confirmar que se aplicarían los mismos pasos
Jonathan
No lo hagas de esta manera. Este es el viejo camino. Usa la nueva forma. Ver enlace a mi respuesta. Este método está lleno de problemas.
Matt
3

Para usar GPU desde el contenedor docker, en lugar de usar Docker nativo, use Nvidia-docker. Para instalar Nvidia Docker, use los siguientes comandos

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
fuente
1

Utilice x11docker por mviereck:

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

Aceleracion de hardware

La aceleración de hardware para OpenGL es posible con la opción -g, --gpu.

Esto funcionará de forma predeterminada en la mayoría de los casos con controladores de código abierto en el host. De lo contrario, eche un vistazo a wiki: dependencias de características. Los controladores NVIDIA de código cerrado necesitan algo de configuración y admiten menos opciones de servidor x11docker X.

Este script es realmente conveniente ya que maneja toda la configuración y configuración. Ejecutar una imagen acoplable en X con gpu es tan simple como

x11docker --gpu imagename
phil294
fuente