Partilhe GPUs entre cargas de trabalho com a partilha de tempo da GPU

Esta página mostra como permitir que várias cargas de trabalho tenham acesso ao partilhar tempo da GPU num único acelerador de hardware da GPU NVIDIA® nos nós do Google Kubernetes Engine (GKE). Ao usar a partilha de tempo da GPU no GKE, pode usar as GPUs associadas de forma mais eficiente e poupar nos custos de execução.

Esta página destina-se a programadores que concebem e implementam cargas de trabalho em clusters do GKE, bem como a administradores e arquitetos que criam e gerem um cluster do GKE, planeiam os requisitos de infraestrutura e recursos e monitorizam o desempenho do cluster. Para saber mais acerca das funções comuns e das tarefas de exemplo que referimos no Google Cloud conteúdo, consulte o artigo Funções e tarefas comuns de utilizadores do GKE.

Antes de ler esta página, certifique-se de que está familiarizado com o funcionamento da partilha de tempo no GKE, incluindo limitações e situações em que deve usar a partilha de tempo da GPU.

Requisitos

  • Versão do GKE: pode ativar a partilha de tempo da GPU em clusters padrão do GKE que executam a versão 1.23.7-gke.1400 e posterior do GKE. Pode usar GPUs de partilha de tempo em clusters do GKE Autopilot que executam a versão 1.29.3-gke.1093000 e posteriores do GKE.
  • Tipo de GPU: pode ativar a partilha de tempo da GPU em todos os modelos de GPU NVIDIA.

Antes de começar

Antes de começar, certifique-se de que realizou as seguintes tarefas:

  • Ative a API Google Kubernetes Engine.
  • Ative a API Google Kubernetes Engine
  • Se quiser usar a CLI gcloud para esta tarefa, instale-a e, em seguida, inicialize-a. Se instalou anteriormente a CLI gcloud, execute o comando gcloud components update para obter a versão mais recente. As versões anteriores da CLI gcloud podem não suportar a execução dos comandos neste documento.

Ative a partilha de tempo da GPU em clusters e pools de nós do GKE

Enquanto administrador da plataforma, tem de ativar a partilha de tempo da GPU num cluster padrão do GKE antes de os programadores poderem implementar cargas de trabalho para usar as GPUs. Para ativar a partilha de tempo da GPU, tem de fazer o seguinte:

  1. Ative a partilha de tempo da GPU num cluster do GKE.
  2. Instale os controladores do dispositivo GPU da NVIDIA (se necessário).
  3. Verifique os recursos da GPU disponíveis nos seus nós.

Os clusters do Autopilot que executam a versão 1.29.3-gke.1093000 e posteriores ativam as GPUs de partilha de tempo por predefinição. A partilha de tempo em clusters do Autopilot está configurada na especificação da carga de trabalho. Para saber mais, consulte a secção Implemente cargas de trabalho que usam GPUs de tempo partilhado.

Ative a partilha de tempo da GPU num cluster padrão do GKE

Pode ativar a partilha de tempo da GPU quando cria clusters padrão do GKE. O node pool predefinido no cluster tem a funcionalidade ativada. Continua a ter de ativar a partilha de tempo da GPU quando cria manualmente novos conjuntos de nós nesse cluster.

gcloud container clusters create CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --cluster-version=CLUSTER_VERSION \
    --machine-type=MACHINE_TYPE \
    --accelerator=type=GPU_TYPE,count=GPU_QUANTITY,gpu-sharing-strategy=time-sharing,max-shared-clients-per-gpu=CLIENTS_PER_GPU,gpu-driver-version=DRIVER_VERSION

Substitua o seguinte:

  • CLUSTER_NAME: o nome do novo cluster.
  • CONTROL_PLANE_LOCATION: a localização do Compute Engine do plano de controlo do seu cluster. Indique uma região para clusters regionais ou uma zona para clusters zonais.
  • CLUSTER_VERSION: a versão do GKE para o painel de controlo e os nós do cluster. Use a versão 1.23.7-gke.1400 ou posterior do GKE. Em alternativa, especifique um canal de lançamento com essa versão do GKE através da flag --release-channel=RELEASE_CHANNEL.
  • MACHINE_TYPE: o tipo de máquina do Compute Engine para os seus nós. Recomendamos que selecione um tipo de máquina otimizado para aceleradores.
  • GPU_TYPE: o tipo de GPU, que tem de ser uma plataforma de GPU NVIDIA como nvidia-tesla-v100.
  • GPU_QUANTITY: o número de GPUs físicas a associar a cada nó no conjunto de nós predefinido.
  • CLIENTS_PER_GPU: o número máximo de contentores que podem partilhar cada GPU física.
  • DRIVER_VERSION: a versão do controlador NVIDIA a instalar. Pode ser uma das seguintes opções:
    • default: instale a versão predefinida do controlador para a sua versão do GKE.
    • latest: instale a versão do controlador mais recente disponível para a sua versão do GKE. Disponível apenas para nós que usam o SO otimizado para contentores.
    • disabled: ignorar a instalação automática de controladores. Tem de instalar manualmente um controlador depois de criar o conjunto de nós. Se omitir gpu-driver-version, esta é a opção predefinida.

Ative a partilha de tempo da GPU num pool de nós do GKE

Pode ativar a partilha de tempo da GPU quando cria manualmente novos conjuntos de nós num cluster do GKE.

gcloud container node-pools create NODEPOOL_NAME \
    --cluster=CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --machine-type=MACHINE_TYPE \
    --accelerator=type=GPU_TYPE,count=GPU_QUANTITY,gpu-sharing-strategy=time-sharing,max-shared-clients-per-gpu=CLIENTS_PER_GPU,gpu-driver-version=DRIVER_VERSION

Substitua o seguinte:

  • NODEPOOL_NAME: o nome do novo conjunto de nós.
  • CLUSTER_NAME: o nome do seu cluster, que tem de executar a versão 1.23.7-gke.1400 ou posterior do GKE.
  • CONTROL_PLANE_LOCATION: a localização do Compute Engine do plano de controlo do seu cluster. Indique uma região para clusters regionais ou uma zona para clusters zonais.
  • MACHINE_TYPE: o tipo de máquina do Compute Engine para os seus nós. Recomendamos que selecione um tipo de máquina otimizado para aceleradores.
  • GPU_TYPE: o tipo de GPU, que tem de ser uma plataforma de GPU NVIDIA como nvidia-tesla-v100.
  • GPU_QUANTITY: o número de GPUs físicas a associar a cada nó no conjunto de nós.
  • CLIENTS_PER_GPU: o número máximo de contentores que podem partilhar cada GPU física.
  • DRIVER_VERSION: a versão do controlador NVIDIA a instalar. Pode ser uma das seguintes opções:

    • default: instale a versão predefinida do controlador para a sua versão do GKE.
    • latest: instale a versão do controlador mais recente disponível para a sua versão do GKE. Disponível apenas para nós que usam o SO otimizado para contentores.
    • disabled: ignorar a instalação automática de controladores. Tem de instalar manualmente um controlador depois de criar o conjunto de nós. Se omitir gpu-driver-version, esta é a opção predefinida.

Instale os controladores de dispositivos da GPU NVIDIA

Antes de continuar, ligue-se ao cluster executando o seguinte comando:

gcloud container clusters get-credentials CLUSTER_NAME

Se optou por desativar a instalação automática de controladores quando criou o cluster, ou se usar uma versão do GKE anterior a 1.27.2-gke.1200, tem de instalar manualmente um controlador NVIDIA compatível para gerir a divisão de partilha de tempo da GPU das GPUs físicas. Para instalar os controladores, implementa um DaemonSet de instalação do GKE que configura os controladores.

Para ver instruções, consulte o artigo Instalar controladores de dispositivos de GPU NVIDIA.

Se planeia usar o aprovisionamento automático de nós no seu cluster, também tem de configurar o aprovisionamento automático de nós com os âmbitos que permitem ao GKE instalar os controladores de dispositivos GPU por si. Para obter instruções, consulte o artigo Usar o aprovisionamento automático dos nós com GPUs.

Valide os recursos de GPU disponíveis nos seus nós

Para verificar se o número de GPUs visíveis nos seus nós corresponde ao número que especificou quando ativou a partilha de tempo da GPU, descreva os seus nós:

kubectl describe nodes NODE_NAME

O resultado é semelhante ao seguinte:

...
Capacity:
  ...
  nvidia.com/gpu:             3
Allocatable:
  ...
  nvidia.com/gpu:             3

Neste exemplo de saída, o número de recursos de GPU no nó é 3 porque o valor especificado para max-shared-clients-per-gpu foi 3 e o número de GPUs físicas a associar ao nó foi 1.count Como outro exemplo, se o número de GPUs físicas fosse 2, o resultado mostraria 6 recursos de GPU atribuíveis, três em cada GPU física.count

Implemente cargas de trabalho que usam a partilha de tempo da GPU

Enquanto operador de aplicações que está a implementar cargas de trabalho de GPU, pode selecionar a partilha de tempo da GPU ativada especificando as etiquetas de nós adequadas num nodeSelector nos seus manifestos. Ao planear os seus pedidos, reveja os limites de pedidos para garantir que o GKE não rejeita as suas implementações.

Para implementar uma carga de trabalho para consumir a partilha de tempo da GPU, conclua os seguintes passos:

  1. Adicione um nodeSelector ao manifesto da carga de trabalho para as seguintes etiquetas:

    • cloud.google.com/gke-gpu-sharing-strategy: time-sharing: seleciona nós que usam a partilha de tempo da GPU.
    • cloud.google.com/gke-max-shared-clients-per-gpu: "CLIENTS_PER_GPU": seleciona nós que permitem que um número específico de contentores partilhe a GPU subjacente.
  2. Adicione o pedido de recurso de nvidia.com/gpu=1GPU à especificação do contentorspec.containers.resources.limits.

Por exemplo, os passos seguintes mostram como implementar três pods num conjunto de nós de partilha de tempo da GPU. O GKE atribui cada contentor à mesma GPU física. Os contentores imprimem o UUID da GPU anexada a esse contentor.

  1. Guarde o seguinte manifesto como gpu-timeshare.yaml:

Piloto automático

        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: cuda-simple
        spec:
          replicas: 3
          selector:
            matchLabels:
              app: cuda-simple
          template:
            metadata:
              labels:
                app: cuda-simple
            spec:
              nodeSelector:
                cloud.google.com/gke-accelerator: "GPU_TYPE"
                cloud.google.com/gke-gpu-sharing-strategy: "time-sharing"
                cloud.google.com/gke-max-shared-clients-per-gpu: "CLIENTS_PER_GPU"
                cloud.google.com/gke-accelerator-count: "GPU_COUNT"
              containers:
              - name: cuda-simple
                image: nvidia/cuda:11.0.3-base-ubi7
                command:
                - bash
                - -c
                - |
                  /usr/local/nvidia/bin/nvidia-smi -L; sleep 300
                resources:
                  limits:
                    nvidia.com/gpu: 1
      

Substitua o seguinte:

  • GPU_TYPE: o tipo de GPU.
  • CLIENTS_PER_GPU: o número de cargas de trabalho que vão usar esta GPU. Para este exemplo, use 3.
  • GPU_COUNT: o número de GPUs físicas a associar ao nó. Para este exemplo, use 1.

Standard

        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: cuda-simple
        spec:
          replicas: 3
          selector:
            matchLabels:
              app: cuda-simple
          template:
            metadata:
              labels:
                app: cuda-simple
            spec:
              nodeSelector:
                cloud.google.com/gke-gpu-sharing-strategy: "SHARING_STRATEGY"
                cloud.google.com/gke-max-shared-clients-per-gpu: "CLIENTS_PER_GPU"
              containers:
              - name: cuda-simple
                image: nvidia/cuda:11.0.3-base-ubi7
                command:
                - bash
                - -c
                - |
                  /usr/local/nvidia/bin/nvidia-smi -L; sleep 300
                resources:
                  limits:
                    nvidia.com/gpu: 1
      

Substitua o seguinte:

  • SHARING_STRATEGY com "partilha de tempo" para pedir partilha de tempo para a sua GPU.
  • CLIENTS_PER_GPU: o número de cargas de trabalho que vão usar esta GPU. Para este exemplo, use 3.
  1. Aplique o manifesto:

    kubectl apply -f gpu-timeshare.yaml
    
  2. Verifique se todos os pods estão em execução:

    kubectl get pods -l=app=cuda-simple
    
  3. Verifique os registos de qualquer Pod para ver o UUID da GPU:

    kubectl logs POD_NAME
    

    O resultado é semelhante ao seguinte:

    GPU 0: Tesla V100-SXM2-16GB (UUID: GPU-0771302b-eb3a-6756-7a23-0adcae8efd47)
    
  4. Se os seus nós tiverem uma GPU física anexada, verifique os registos de qualquer outro pod no mesmo nó para confirmar se o UUID da GPU é o mesmo:

    kubectl logs POD2_NAME
    

    O resultado é semelhante ao seguinte:

    GPU 0: Tesla V100-SXM2-16GB (UUID: GPU-0771302b-eb3a-6756-7a23-0adcae8efd47)
    

Use a partilha de tempo da GPU com GPUs multi-instância

Enquanto administrador da plataforma, pode querer combinar várias funcionalidades de GPU do GKE. A partilha de tempo da GPU funciona com GPUs de várias instâncias, que dividem uma única GPU física em até sete partes. Estas partições estão isoladas umas das outras. Pode configurar a partilha de tempo da GPU para cada partição de GPU de várias instâncias.

Por exemplo, se definir gpu-partition-size como 1g.5gb, a GPU subjacente seria dividida em sete partições. Se também definir max-shared-clients-per-gpu como 3, cada partição suporta até três contentores, num total de até 21 dispositivos de partilha de tempo da GPU disponíveis para atribuição nessa GPU física. Para saber como o gpu-partition-size é convertido em partições reais, consulte o artigo Partições de GPU com várias instâncias.

Para criar um cluster de GPU de várias instâncias com a partilha de tempo da GPU ativada, execute o seguinte comando:

Piloto automático

Com o Autopilot, a partilha de tempo da GPU e as GPUs de várias instâncias podem ser usadas em conjunto através da utilização de ambos os conjuntos de seletores de nós.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cuda-simple
spec:
  replicas: 7
  selector:
    matchLabels:
      app: cuda-simple
  template:
    metadata:
      labels:
        app: cuda-simple
    spec:
      nodeSelector:
        cloud.google.com/gke-gpu-partition-size: 1g.5gb
        cloud.google.com/gke-gpu-sharing-strategy: time-sharing
        cloud.google.com/gke-max-shared-clients-per-gpu: "3"
        cloud.google.com/gke-accelerator: nvidia-tesla-a100
        cloud.google.com/gke-accelerator-count: "1"
      containers:
      - name: cuda-simple
        image: nvidia/cuda:11.0.3-base-ubi7
        command:
        - bash
        - -c
        - |
          /usr/local/nvidia/bin/nvidia-smi -L; sleep 300
        resources:
          limits:
            nvidia.com/gpu: 1

Standard

Com o tipo Standard, tem de criar um cluster de várias instâncias com partilha de tempo da GPU executando o seguinte comando:

gcloud container node-pools create NODEPOOL_NAME \
    --cluster=CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --machine-type=MACHINE_TYPE \
    --accelerator=type=nvidia-tesla-a100,count=GPU_QUANTITY,gpu-partition-size=PARTITION_SIZE,gpu-sharing-strategy=time-sharing,max-shared-clients-per-gpu=CLIENTS_PER_GPU,gpu-driver-version=DRIVER_VERSION

Substitua PARTITION_SIZE pelo tamanho da partição da GPU de várias instâncias que quer, como 1g.5gb.

Limitações

  • Com a partilha de tempo da GPU, o GKE aplica o isolamento do espaço de endereços, o isolamento do desempenho e o isolamento de erros entre contentores que partilham uma GPU física. No entanto, os limites de memória não são aplicados nas GPUs. Para evitar problemas de falta de memória (OOM), defina limites de memória da GPU nas suas cargas de trabalho. Para evitar problemas de segurança, implemente apenas cargas de trabalho que estejam no mesmo limite de confiança para a partilha de tempo da GPU.
  • Para evitar comportamentos inesperados durante a atribuição de capacidade, o GKE pode rejeitar determinados pedidos de partilha de tempo da GPU. Para ver detalhes, consulte o artigo Pedidos de GPU para partilha de tempo da GPU.
  • O número máximo de contentores que podem usar a partilha de tempo numa única GPU física é de 48. Ao planear a configuração de partilha de tempo da GPU, considere as necessidades de recursos das suas cargas de trabalho e a capacidade das GPUs físicas subjacentes para otimizar o desempenho e a capacidade de resposta.

O que se segue?