Usando GPU de um contêiner de docker?

164

Estou procurando uma maneira de usar a GPU de dentro de um contêiner de docker.

O contêiner executará código arbitrário, portanto, não quero usar o modo privilegiado.

Alguma dica?

De pesquisas anteriores, entendi que run -ve / ou o LXC cgroupera o caminho a seguir, mas não sei ao certo como fazer isso exatamente

Regan
fonte
Consulte stackoverflow.com/questions/17792161/…, que é semelhante à sua necessidade.
precisa saber é o seguinte
1
@NicolasGoy O link era bom, mas não tão útil, pois não posso usar privilégios por motivos de segurança. O lxc-cgroups era um bom indicador, mas não o suficiente. Eu encontrei uma maneira, e eu vou responder quando tudo será polido.
Regan

Respostas:

132

A resposta de Regan é ótima, mas está um pouco desatualizada, pois a maneira correta de fazer isso é evitar o contexto de execução lxc, pois o Docker descartou o LXC como o contexto de execução padrão no docker 0.9.

Em vez disso, é melhor falar ao docker sobre os dispositivos da nvidia por meio do sinalizador --device e usar o contexto de execução nativo em vez do lxc.

Meio Ambiente

Estas instruções foram testadas no seguinte ambiente:

  • Ubuntu 14.04
  • CUDA 6.5
  • Instância da AWS GPU.

Instale o driver nvidia e cuda no seu host

Consulte CUDA 6.5 na instância da AWS GPU executando o Ubuntu 14.04 para obter a configuração da máquina host.

Instalar o 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

Encontre seus 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

Execute o contêiner do Docker com o driver da nvidia pré-instalado

Criei uma imagem do docker com os drivers cuda pré-instalados. O dockerfile está disponível no dockerhub se você quiser saber como essa imagem foi criada.

Você deseja personalizar este comando para corresponder aos seus dispositivos nvidia. Aqui está o que funcionou para mim:

 $ 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 se o CUDA está instalado corretamente

Isso deve ser executado de dentro do contêiner do docker que você acabou de lançar.

Instale amostras CUDA:

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

Exemplo de build deviceQuery:

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

Se tudo funcionou, você deverá ver a seguinte saída:

deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 6.5, CUDA Runtime Version = 6.5, NumDevs =    1, Device0 = GRID K520
Result = PASS
Tleyden
fonte
3
Por que você instala o lxc-docker se não precisa do lxc?
MP0
4
Eu tenho o CUDA 5.5 no host e o CUDA 6.5 em um contêiner criado a partir da sua imagem. O CUDA está trabalhando no host e eu passei os dispositivos para o contêiner. O contêiner visualiza as GPUs, ls -la /dev | grep nvidiamas o CUDA não consegue encontrar nenhum dispositivo compatível com o CUDA: ./deviceQuery ./deviceQuery Starting... CUDA Device Query (Runtime API) version (CUDART static linking) cudaGetDeviceCount returned 38 -> no CUDA-capable device is detected Result = FAIL isso ocorre devido à incompatibilidade das bibliotecas CUDA no host e no contêiner?
Brunetto
1
Não sei, você pode perguntar nos fóruns da nvidia. Supondo que a incompatibilidade de versão seja um problema, você pode pegar esse Dockerfile e editá-lo para ter os drivers CUDA 5.5, depois reconstruir uma nova imagem do Docker e usá-lo.
tleyden
3
Você pode explicar por que a imagem precisa instalar o driver da nvidia? Eu pensei que apenas host instalar o driver da nvidia (e usar - dispositivo ...) é suficiente?
Helin Wang
2
Atualmente, não há como fazer isso se você tiver o Windows como host.
Souradeep Nanda
45

Escrever uma resposta atualizada, pois a maioria das respostas já existentes está obsoleta a partir de agora.

Versões anteriores ao que Docker 19.03costumava exigir nvidia-docker2e o --runtime=nvidiasinalizador.

Desde então Docker 19.03, você precisa instalar o nvidia-container-toolkitpacote e depois usar o --gpus allsinalizador.

Então, aqui estão o básico,

Instalação do pacote

Instale o nvidia-container-toolkitpacote de acordo com a documentação oficial no Github .

Para sistemas operacionais baseados em Redhat, execute o seguinte 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 operacionais baseados em Debian, execute o seguinte 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

Executando a janela de encaixe com suporte à GPU

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

Observe que o sinalizador --gpus allé usado para atribuir todos os gpus disponíveis ao contêiner do docker.

Para atribuir gpu específica ao contêiner do docker (no caso de várias GPUs disponíveis em sua máquina)

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

Ou

docker run --name my_first_gpu_container --gpus '"device=0"' nvidia/cuda
Rohit
fonte
5
A partir de 2019, essa é a maneira correta de usar a GPU em contêineres de docker.
Timur Bakeyev 20/10/19
1
Alguém já tentou isso dentro de um trabalho em lote na AWS?
medley56
1
Eu acredito que isso é mais relevante. Gostaria de ter encontrado isso antes, apesar de ter que adaptar as instruções do github.com/NVIDIA/nvidia-docker para trabalhar com o Ubuntu
20.04
40

Ok, finalmente consegui fazê-lo sem usar o modo --privileged.

Estou executando no servidor ubuntu 14.04 e estou usando o ultimo cuda (6.0.37 para linux 13.04 64 bits).


Preparação

Instale o driver da nvidia e o cuda no seu host. (pode ser um pouco complicado, então eu sugiro que você siga este guia /ubuntu/451672/installing-and-testing-cuda-in-ubuntu-14-04 )

ATENÇÃO: É realmente importante que você mantenha os arquivos usados ​​para a instalação do host cuda


Faça o Docker Daemon executar usando lxc

Precisamos executar o docker daemon usando o driver lxc para poder modificar a configuração e conceder ao contêiner acesso ao dispositivo.

Utilização única:

sudo service docker stop
sudo docker -d -e lxc

Configuração permanente Modifique seu arquivo de configuração do docker localizado em / etc / default / docker Altere a linha DOCKER_OPTS adicionando '-e lxc' Aqui está minha linha após a modificação

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

Em seguida, reinicie o daemon usando

sudo service docker restart

Como verificar se o daemon usa efetivamente o driver lxc?

docker info

A linha do Driver de Execução deve ficar assim:

Execution Driver: lxc-1.0.5

Crie sua imagem com os drivers NVIDIA e CUDA.

Aqui está um Dockerfile básico para criar uma imagem compatível com 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.

Execute sua imagem.

Primeiro, você precisa identificar seu número principal associado ao seu dispositivo. A maneira mais fácil é executar o seguinte comando:

ls -la /dev | grep nvidia

Se o resultado estiver em branco, o lançamento de uma das amostras no host deve fazer o truque. O resultado deve ser assim. insira a descrição da imagem aqui Como você pode ver, há um conjunto de 2 números entre o grupo e a data. Esses 2 números são chamados de números maiores e menores (escritos nessa ordem) e projetam um dispositivo. Usaremos apenas os principais números por conveniência.

Por que ativamos o driver lxc? Para usar a opção lxc conf que nos permite permitir que nosso contêiner acesse esses dispositivos. A opção é: (eu recomendo usar * para o número menor, pois isso reduz o tamanho do comando executar)

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

Então, se eu quiser iniciar um contêiner (supondo que o nome da imagem seja cuda).

docker run -ti --lxc-conf='lxc.cgroup.devices.allow = c 195:* rwm' --lxc-conf='lxc.cgroup.devices.allow = c 243:* rwm' cuda
Regan
fonte
Você pode compartilhar o contêiner?
precisa saber é o seguinte
1
O Docker tem uma --deviceopção para permitir que o contêiner acesse o dispositivo do host. No entanto, tentei usar --device=/dev/nvidia0para permitir que o contêiner do docker executasse cuda e falhou.
shiquanwang
4
Eu, então, conseguiu com expondo tudo /dev/nvidiao, /dev/nvidia1, /dev/nvidiactle /dev/nvidia-uvmcom --device. Embora não saiba o porquê.
shiquanwang
A opção --device não foi implementada quando tive que encontrar esta solução. Você precisa de pelo menos nvidia0 ou nvidia1 (placa gráfica) e nvidiactl (dispositivo geral da nvidia) e nvidia-uvm (dispositivo de memória da United).
Regan
2
Obrigado por suas dicas sobre o /dev/nvidia*@Regan. Para @ChillarAnand I fez um cuda-estivador
shiquanwang
29

Acabamos de lançar um repositório experimental do GitHub, que deve facilitar o processo de uso de GPUs NVIDIA dentro de contêineres do Docker.

3XX0
fonte
4
Existe suporte para windows? Parece que não, mas talvez esteja perdendo alguma coisa.
Chama
6
Não há suporte para Windows. A execução do contêiner CUDA requer drivers Nvidia para Linux e acesso a dispositivos Linux representando GPU, por exemplo, / dev / nvidia0. Esses dispositivos e drivers não estão disponíveis quando o Docker está instalado no Windows e em execução na máquina virtual do VirtualBox.
Paweł Bylica
Ainda precisa das declarações --device no comando run? Eu criei um contêiner da nvidia / cuda e o contêiner funciona bem, mas o aplicativo (Wowza) não reconhece as GPUs, mas funciona bem quando executado diretamente no host (esse host, então eu sei que os drivers estão bem) . Estou executando o 361.28. O host é o EC2 usando o NVidia AMI em g2.8xlarge.
rainabba 27/02
Não tudo é cuidado por nvidia-janela de encaixe, você deve ser capaz de executar nvidia-sor dentro do recipiente e ver os seus dispositivos
3XX0
22

Os aprimoramentos recentes da NVIDIA produziram uma maneira muito mais robusta de fazer isso.

Essencialmente, eles encontraram uma maneira de evitar a necessidade de instalar o driver CUDA / GPU dentro dos contêineres e combiná-lo com o módulo do kernel do host.

Em vez disso, os drivers estão no host e os contêineres não precisam deles. Ele requer um docker-cli modificado no momento.

Isso é ótimo, porque agora os contêineres são muito mais portáteis.

insira a descrição da imagem aqui

Um teste rápido no 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 obter mais detalhes, consulte: Contêiner do Docker ativado por GPU e: https://github.com/NVIDIA/nvidia-docker

Matt
fonte
Isso funciona bem quando você obtém todas as etapas. A Nvidia não fornece tudo em um só lugar, mas este exemplo fornece tudo o que você precisa para fazer funcionar com um caso de uso comum.
KobeJohn
@KobeJohn - Acabei de seguir as instruções de instalação, como usar a linha de comando e garantir que meus contêineres herdem dos cuda. Apenas funciona para mim.
22418 Matt
1
Na verdade, você pode dar os cenários da vida real em que o uso da nvidia-docker faz sentido?
Suncatcher 6/18
@Suncatcher - estou usando-o em um cluster que requer acesso à GPU para renderização em 3D. A ancoragem dos aplicativos tornou as coisas mais simples de implantar e manter.
Matt
17

Atualizado para cuda-8.0 no 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. Execute seu contêiner

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

Você deve ver uma saída semelhante a:

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

Jonathan
fonte
3
Eu recebo a seguinte saída. cudaGetDeviceCount devolvido 38 -> nenhum dispositivo CUDA capaz é detectado Resultado = FALHA
Soichi Hayashi
Resposta tardia, mas isso significa que você provavelmente não tem uma GPU nessa máquina
Jonathan
Uma versão do Cuda-9 seria quase a mesma?
huseyin tugrul buyukisik
@huseyintugrulbuyukisik veja esta resposta no askubuntu askubuntu.com/questions/967332/… , eu diria que você poderia usar essa resposta como um guia, mas não trabalhei com o cuda 9 para confirmar que os mesmos passos se aplicariam
Jonathan
Não faça assim. Esta é a maneira antiga. Use o novo caminho. Veja o link da minha resposta. Este método está cheio de problemas.
Matt
3

Para usar a GPU do contêiner do docker, em vez de usar o Docker nativo, use o Nvidia-docker. Para instalar a docker Nvidia, use os seguintes 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
fonte
1

Use o x11docker by mviereck:

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

Aceleraçao do hardware

A aceleração de hardware para o OpenGL é possível com a opção -g, --gpu.

Isso funcionará imediatamente na maioria dos casos, com drivers de código aberto no host. Caso contrário, dê uma olhada no wiki: dependências de recursos. Os drivers NVIDIA de código fechado precisam de alguma configuração e suportam menos opções de servidor x11docker X.

Este script é realmente conveniente, pois lida com toda a configuração. A execução de uma imagem do docker no X com gpu é tão simples quanto

x11docker --gpu imagename
phil294
fonte