Como executar contêineres do Docker Compose com acesso à GPU

0
25


O acesso à GPU no Docker permite hospedar cargas de trabalho exigentes, como aplicativos de aprendizado de máquina. As GPUs não estão disponíveis automaticamente quando você inicia um novo contêiner, mas podem ser ativadas com o --gpus bandeira para docker run ou adicionar campos adicionais a um docker-compose.yml procedimentos.

Neste artigo, mostraremos como habilitar o suporte a GPU no Docker Compose. Você precisará do Docker Compose versão v1.28 ou posterior para seguir o guia. As GPUs não são compatíveis com o Compose v1.18 e anteriores; as versões entre v1.19 e v1.27 usam uma estrutura de campo herdada que oferece menos controle.

Prepare seu sistema

Seu host do Docker deve estar pronto antes que você possa expor sua GPU de hardware. Embora os contêineres compartilhem o kernel de seu host, eles não podem ver os pacotes do sistema instalados nele. Um contêiner simples não terá os drivers de dispositivo que interagem com sua GPU.

Você pode habilitar o suporte para GPUs NVIDIA instalando o NVIDIA Docker Container Toolkit:

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 update
sudo apt install -y nvidia-docker2
sudo systemctl restart docker

Este pacote envolve o tempo de execução do contêiner do Docker com uma interface para o driver NVIDIA em seu host. inspecionando seu /etc/docker/daemon.json O arquivo confirmará que o tempo de execução do contêiner configurado foi alterado. O kit de ferramentas NVIDIA lidará com a injeção de conexões de dispositivos GPU quando novos contêineres forem iniciados. Em seguida, ele será transferido para o tempo de execução normal do contêiner.

$ cat /etc/docker/daemon.json
{
    "runtimes": {
        "nvidia": {
            "path": "nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
}

preparando sua imagem

O acesso à GPU no Docker também depende da configuração correta da imagem do contêiner. Geralmente é mais fácil basear a imagem em uma variante de nvidia/cuda. Este ponto de partida fornecido pela NVIDIA vem pré-configurado com suporte CUDA. Instale qualquer linguagem de programação necessária e copie seu código dependente de GPU:

FROM nvidia/cuda:11.4.0-base-ubuntu20.04
RUN apt update && 
  apt-get install -y python3 python3-pip &&
  pip install tensorflow-gpu

COPY tensor.py .
ENTRYPONT ["python3", "tensor.py"]

Você deve usar a mesma versão do CUDA que instalou em seu host. Você pode verificar isso executando nvidia-smi:

$ nvidia-smi
Tue May 10 19:15:00 2022       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 470.103.01   Driver Version: 470.103.01   CUDA Version: 11.4     |
|-------------------------------+----------------------+----------------------+
...

Agora você pode escrever um arquivo Docker Compose para iniciar seu contêiner com um anexo de GPU.

Acesse GPUs no Docker Compose

GPUs são mencionados em um docker-compose.yml arquivo através do deploy.resources.reservations.devices campo dentro de seus serviços que precisam deles. Esse mecanismo permite identificar as GPUs que você deseja anexar. Cada dispositivo selecionado será fornecido aos seus contêineres.

Aqui está um exemplo simples que inicia um contêiner usando o nvidia/cuda imagem. Ele emitirá informações sobre sua GPU quando o contêiner for iniciado.

services:
  app:
    image: nvidia/cuda:11.4.0-base-ubuntu20.04
    command: nvidia-smi
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              capabilities: [gpu]

a deploy.resources.reservations.devices O campo especifica os dispositivos que seu contêiner pode usar. Configuração do driver uma nvidia e adicionando o gpu A capacidade define um dispositivo GPU.

Corre docker-compose up (qualquer docker compose up para Compose v2) para iniciar seu contêiner:

$ docker compose up
Creating network "scratch_default" with the default driver
Creating scratch_app_1 ... done
Attaching to scratch_app_1
app_1  | Tue May 10 14:21:14 2022       
app_1  | +-----------------------------------------------------------------------------+
app_1  | | NVIDIA-SMI 470.103.01   Driver Version: 470.103.01   CUDA Version: 11.4     |
app_1  | |-------------------------------+----------------------+----------------------+

O contêiner deve ter acesso com sucesso à sua GPU. As versões de driver e CUDA corresponderão àquelas instaladas em seu host.

Usando várias GPUs

Seu contêiner recebe acesso a todas as GPUs em seu sistema, a menos que uma configuração adicional seja fornecida. Existem duas maneiras diferentes de acessar um subconjunto de seus dispositivos GPU.

Acesso a um número fixo de dispositivos

a count O campo reserva um número específico de dispositivos. Neste exemplo, um sistema com duas GPUs fornecerá uma delas ao contêiner. É arbitrário qual deles será selecionado.

services:
  app:
    image: nvidia/cuda:11.4.0-base-ubuntu20.04
    command: nvidia-smi
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]

Acesso a dispositivos específicos

Você pode identificar dispositivos individuais em seu sistema usando o device_ids campo. Isso aceita uma matriz de IDs de dispositivo com índice 0 para fornecer ao contêiner. Você pode encontrar esses IDs listando suas GPUs com nvidia-smi:

$ nvidia-smi --list-gpus
GPU 0: NVIDIA GeForce GTX 1080 Ti (UUID: GPU-5ba4538b-234f-2c18-6a7a-458d0a7fb348)
GPU 1: NVIDIA GeForce GTX 1080 Ti (UUID: GPU-d5ce9af3-710c-4222-95f8-271db933d438)
GPU 2: NVIDIA GeForce GTX 1080 Ti (UUID: GPU-50d4eb4f-7b08-4f8f-8d20-27d797fb7f19)
GPU 3: NVIDIA GeForce GTX 1080 Ti (UUID: GPU-bed2d40a-c6e7-4547-8d7d-a1576c5247b2)

Para acessar de forma confiável os dois últimos dispositivos da lista, inclua seus IDs de dispositivo nas configurações de serviço:

services:
  app:
    image: nvidia/cuda:11.4.0-base-ubuntu20.04
    command: nvidia-smi
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              device_ids: ["2", "3"]
              capabilities: [gpu]

Você pode usar count qualquer device_ids em cada uma de suas definições de serviço. Você receberá um erro ao executar docker-compose up se você tentar combinar ambos, especifique um ID de dispositivo inválido ou use um valor de count que é maior que o número de GPUs em seu sistema.

Resumo

Versões modernas do Docker Compose suportam acesso à GPU via deploy.resources função de reserva do dispositivo. Você ainda é responsável por preparar seu ambiente de host e usar uma imagem de contêiner habilitada para GPU. Uma vez que isso é corrigido, execute docker-compose up -d é mais simples do que lembrar de incluir o --gpus all marque cada vez que usar docker run.

Você pode comprometer sua docker-compose.yml arquivo no controle de origem para que todos tenham acesso automático à GPU. Você deve garantir a padronização em versões consistentes do driver NVIDIA, pois a versão usada por sua imagem deve corresponder à instalada em seus hosts. No futuro, o suporte a GPU do Docker também poderá funcionar com dispositivos Intel e AMD, mas tentar usá-lo hoje resultará em erro. A NVIDIA é o único fornecedor de GPU atualmente suportado pelo projeto Moby.