Condividere le GPU con più carichi di lavoro utilizzando NVIDIA MPS


Questa pagina spiega come utilizzare il servizio con processi multipli (MPS) CUDA per consentire a più carichi di lavoro di condividere un singolo acceleratore hardware GPU NVIDIA nei nodi di Google Kubernetes Engine (GKE).

Panoramica

NVIDIA MPS è una soluzione di condivisione della GPU che consente a più container di condividere un singolo hardware GPU NVIDIA fisico collegato a un nodo.

NVIDIA MPS si basa sul servizio con processi multipli di NVIDIA su CUDA. NVIDIA MPS è un'implementazione alternativa e compatibile a livello binario dell'API CUDA progettata per consentire in modo trasparente l'esecuzione simultanea di applicazioni CUDA multi-processo cooperative su un singolo dispositivo GPU.

Con NVIDIA MPS, puoi specificare il numero massimo di container condivisi di una GPU fisica. Questo valore determina la quantità di potenza della GPU fisica che ogni container riceve, in termini delle seguenti caratteristiche:

Per scoprire di più su come vengono pianificate le GPU con NVIDIA MPS e quando utilizzare CUDA MPS, consulta la sezione Informazioni sulle soluzioni di condivisione della GPU in GKE.

Chi dovrebbe utilizzare questa guida

Le istruzioni riportate in questa sezione si applicano se rientri in una delle seguenti categorie:

  • Amministratore della piattaforma: crea e gestisce un cluster GKE, pianifica i requisiti di infrastruttura e risorse e monitora le prestazioni del cluster.
  • Sviluppatore di applicazioni: progetta ed esegue il deployment di carichi di lavoro sui cluster GKE. Se vuoi istruzioni per richiedere NVIDIA MPS con GPU, consulta Esegui il deployment di workload che utilizzano NVIDIA MPS con GPU.

Requisiti

  • Versione GKE: puoi abilitare la condivisione della GPU con NVIDIA MPS sui cluster GKE Standard che eseguono la versione GKE 1.27.7-gke.1088000 e successive.
  • Tipo di GPU: puoi attivare NVIDIA MPS per tutti i tipi di GPU NVIDIA.

Prima di iniziare

Prima di iniziare, assicurati di aver eseguito le seguenti operazioni:

  • Attiva l'API Google Kubernetes Engine.
  • Attiva l'API Google Kubernetes Engine
  • Se vuoi utilizzare Google Cloud CLI per questa attività, installala e poi inizializzala. Se hai già installato gcloud CLI, scarica l'ultima versione eseguendo gcloud components update.
  • Assicurati di disporre di una quota sufficiente di GPU NVIDIA. Se hai bisogno di più quota, consulta la sezione Richiesta di aumento della quota.
  • Pianifica la capacità della GPU in base alle esigenze di risorse dei workload e alla capacità della GPU sottostante.
  • Esamina le limitazioni per NVIDIA MPS con GPU.

Abilita NVIDIA MPS con GPU sui cluster GKE

In qualità di amministratore della piattaforma, devi abilitare NVIDIA MPS con GPU su un cluster GKE Standard. Successivamente, gli sviluppatori di applicazioni possono eseguire il deployment dei carichi di lavoro per utilizzare NVIDIA MPS con le GPU. Per abilitare NVIDIA MPS con GPU su GKE, segui questi passaggi:

  1. Abilita NVIDIA MPS con GPU su un nuovo cluster GKE.
  2. Installa i driver di dispositivo GPU NVIDIA (se necessario).
  3. Verifica le risorse GPU disponibili sui nodi.

Abilita NVIDIA MPS con GPU su un cluster GKE

Puoi abilitare NVIDIA MPS con GPU quando crei cluster GKE Standard. La funzionalità è attivata nel pool di nodi predefinito del cluster. Devi comunque abilitare NVIDIA MPS con le GPU quando crei manualmente nuovi node pool nel cluster.

Crea un cluster con NVIDIA MPS abilitato utilizzando Google Cloud CLI:

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=mps,max-shared-clients-per-gpu=CLIENTS_PER_GPU,gpu-driver-version=DRIVER_VERSION

Sostituisci quanto segue:

  • CLUSTER_NAME: il nome del nuovo cluster.
  • CONTROL_PLANE_LOCATION: la posizione di Compute Engine del control plane del tuo cluster. Fornisci una regione per i cluster regionali o una zona per i cluster zonali. Il tipo di GPU che utilizzi deve essere disponibile nella regione selezionata.
  • CLUSTER_VERSION: la versione di GKE per il control plane e i nodi del cluster. Utilizza GKE 1.27.7-gke.1088000 o versioni successive. In alternativa, specifica un canale di rilascio con quella versione di GKE utilizzando il flag --release-channel=RELEASE_CHANNEL.
  • MACHINE_TYPE: il tipo di macchina Compute Engine per i nodi.
  • GPU_TYPE: il tipo di GPU, che deve essere una piattaforma GPU NVIDIA come nvidia-tesla-v100.
  • GPU_QUANTITY: il numero di GPU fisiche da collegare a ogni nodo nel pool di nodi predefinito.
  • CLIENTS_PER_GPU: il numero massimo di container che possono condividere ogni GPU fisica.
  • DRIVER_VERSION: la versione del driver NVIDIA da installare. Può corrispondere a uno dei seguenti:
    • default: installa la versione del driver predefinita per la tua versione di GKE.
    • latest: installa la versione più recente del driver disponibile per la tua versione di GKE. Disponibile solo per i nodi che utilizzano Container-Optimized OS.
    • disabled: salta l'installazione automatica del driver. Devi installare manualmente un driver dopo aver creato il pool di nodi. Se ometti gpu-driver-version, questa è l'opzione predefinita.

Attiva NVIDIA MPS con GPU in un nuovo pool di nodi

Puoi abilitare NVIDIA MPS con GPU quando crei manualmente nuovi node pool in un cluster GKE. Crea un pool di nodi con NVIDIA MPS abilitato utilizzando Google Cloud CLI:

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

Sostituisci quanto segue:

  • NODEPOOL_NAME: il nome del nuovo pool di nodi.
  • CLUSTER_NAME: il nome del cluster, che deve eseguire GKE versione 1.27.7-gke.1088000 o successive.
  • CONTROL_PLANE_LOCATION: la posizione di Compute Engine del control plane del tuo cluster. Fornisci una regione per i cluster regionali o una zona per i cluster zonali.
  • MACHINE_TYPE: il tipo di macchina Compute Engine per i nodi. Per le GPU A100, utilizza un tipo di macchina A2. Per tutte le altre GPU, utilizza un tipo di macchina N1.
  • GPU_TYPE: il tipo di GPU, che deve essere una piattaforma GPU NVIDIA come nvidia-tesla-v100.
  • GPU_QUANTITY: il numero di GPU fisiche da collegare a ogni nodo nel pool di nodi.
  • CONTAINER_PER_GPU: il numero massimo di container che possono condividere ogni GPU fisica.
  • DRIVER_VERSION: la versione del driver NVIDIA da installare. Può corrispondere a uno dei seguenti:

    • default: installa la versione del driver predefinita per la tua versione di GKE.
    • latest: installa la versione più recente del driver disponibile per la tua versione di GKE. Disponibile solo per i nodi che utilizzano Container-Optimized OS.
    • disabled: salta l'installazione automatica del driver. Devi installare manualmente un driver dopo aver creato il pool di nodi. Se ometti gpu-driver-version, questa è l'opzione predefinita.

Installa i driver del dispositivo GPU NVIDIA

Se hai scelto di disattivare l'installazione automatica dei driver durante la creazione del cluster o se utilizzi una versione di GKE precedente alla 1.27.2-gke.1200, devi installare manualmente un driver NVIDIA compatibile per gestire la divisione NVIDIA MPS delle GPU fisiche. Per installare i driver, devi eseguire il deployment di un DaemonSet di installazione di GKE che configura i driver.

Per istruzioni, consulta Installazione dei driver di dispositivo GPU NVIDIA.

Verifica le risorse GPU disponibili

Puoi verificare che il numero di GPU nei nodi corrisponda al numero specificato quando hai attivato NVIDIA MPS. Puoi anche verificare che il daemon di controllo NVIDIA MPS sia in esecuzione.

Verifica le risorse GPU disponibili sui nodi

Per verificare le risorse GPU disponibili sui nodi, esegui questo comando:

kubectl describe nodes NODE_NAME

Sostituisci NODE_NAME con il nome del nodo.

L'output è simile al seguente:

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

In questo output, il numero di risorse GPU sul nodo è 3 a causa dei seguenti valori:

  • Il valore in max-shared-clients-per-gpu è 3.
  • Il count delle GPU fisiche da collegare al nodo è 1. Se il count delle GPU fisiche era 2, l'output mostrerà 6 risorse GPU allocabili, tre su ogni GPU fisica.

Verifica che il daemon di controllo MPS sia in esecuzione

Il plug-in del dispositivo GPU esegue un controllo di integrità sul daemon di controllo MPS. Quando il daemon di controllo MPS è integro, puoi eseguire il deployment di un container.

Per verificare lo stato di MPS, esegui questo comando:

kubectl logs -l k8s-app=nvidia-gpu-device-plugin -n kube-system --tail=100 | grep MPS

L'output è simile al seguente:

I1118 08:08:41.732875       1 nvidia_gpu.go:75] device-plugin started
...
I1110 18:57:54.224832       1 manager.go:285] MPS is healthy, active thread percentage = 100.0
...

Nell'output potresti vedere che si sono verificati i seguenti eventi:

  • L'errore failed to start GPU device manager precede l'errore MPS is healthy. Questo errore è temporaneo. Se visualizzi il messaggio MPS is healthy, significa che il daemon di controllo è in esecuzione.
  • Il messaggio active thread percentage = 100.0 indica che l'intera risorsa GPU fisica ha un thread completamente attivo.

Esegui il deployment di carichi di lavoro che utilizzano MPS

In qualità di operatore di applicazioni che esegue il deployment di carichi di lavoro GPU, puoi indicare a GKE di condividere le unità di condivisione MPS nella stessa GPU fisica. Nel seguente manifest, richiedi una GPU fisica e imposta max-shared-clients-per-gpu=3. La GPU fisica riceve tre unità di condivisione MPS e avvia un job nvidia/samples:nbody con tre pod (container) in esecuzione in parallelo.

  1. Salva il manifest come gpu-mps.yaml:

      apiVersion: batch/v1
      kind: Job
      metadata:
        name: nbody-sample
      spec:
        completions: 3
        parallelism: 3
        template:
          spec:
            hostIPC: true
            nodeSelector:
              cloud.google.com/gke-gpu-sharing-strategy: mps
            containers:
              - name: nbody-sample
                image: nvidia/samples:nbody
                command: ["/tmp/nbody"]
                args: ["-benchmark", "-i=5000"]
                resources:
                  limits:
                    nvidia.com/gpu: 1
            restartPolicy: "Never"
        backoffLimit: 1
    

    In questo manifest:

    • hostIPC: true consente ai pod di comunicare con il daemon di controllo MPS. È obbligatorio. Tuttavia, tieni presente che la configurazione hostIPC: true consente al container di accedere alla risorsa host, il che introduce rischi per la sicurezza.
    • 5000 iterazioni eseguite in modalità benchmark.
  2. Applica il manifest:

    kubectl apply -f gpu-mps.yaml
    
  3. Verifica che tutti i pod siano in esecuzione:

    kubectl get pods
    

    L'output è simile al seguente:

    NAME                           READY   STATUS    RESTARTS   AGE
    nbody-sample-6948ff4484-54p6q   1/1     Running   0          2m6s
    nbody-sample-6948ff4484-5qs6n   1/1     Running   0          2m6s
    nbody-sample-6948ff4484-5zpdc   1/1     Running   0          2m5s
    
  4. Controlla i log dei pod per verificare che il job sia stato completato:

    kubectl logs -l job-name=nbody-sample -f
    

    L'output è simile al seguente:

    ...
    > Compute 8.9 CUDA device: [NVIDIA L4]
    18432 bodies, total time for 5000 iterations: 9907.976 ms
    = 171.447 billion interactions per second
    = 3428.941 single-precision GFLOP/s at 20 flops per interaction
    ...
    

    Poiché GKE esegue 50.000 iterazioni, il log potrebbe richiedere diversi minuti.

Esegui la pulizia

Elimina i job e tutti i relativi pod eseguendo questo comando:

kubectl delete job --all

Limita la memoria del dispositivo bloccato e il thread attivo con NVIDIA MPS

Per impostazione predefinita, quando utilizzi la GPU con NVIDIA MPS su GKE, le seguenti variabili di ambiente CUDA vengono inserite nel carico di lavoro della GPU:

  • CUDA_MPS_ACTIVE_THREAD_PERCENTAGE: questa variabile indica la percentuale di thread disponibili che ogni unità di condivisione MPS può utilizzare. Per impostazione predefinita, ogni unità di condivisione MPS della GPU è impostata su 100 / MaxSharedClientsPerGPU per ottenere una parte uguale del calcolo della GPU in termini di multiprocessore di flusso.
  • CUDA_MPS_PINNED_DEVICE_MEM_LIMIT: questa variabile limita la quantità di memoria GPU che può essere allocata da un'unità di condivisione MPS della GPU. Per impostazione predefinita, ogni unità di condivisione MPS della GPU è impostata su total mem / MaxSharedClientsPerGPU per ottenere una parte uguale della memoria GPU.

Per impostare il limite di risorse per i carichi di lavoro GPU, configura queste variabili di ambiente NVIDIA MPS:

  1. Esamina e crea l'immagine dell'esempio cuda-mps in GitHub.

  2. Salva il seguente manifest come cuda-mem-and-sm-count.yaml:

    apiVersion: v1
    kind: Pod
    metadata:
      name: cuda-mem-and-sm-count
    spec:
      hostIPC: true
      nodeSelector:
        cloud.google.com/gke-gpu-sharing-strategy: mps
      containers:
        - name: cuda-mem-and-sm-count
          image: CUDA_MPS_IMAGE
          securityContext:
            privileged: true
          resources:
            limits:
              nvidia.com/gpu: 1
    

    Sostituisci CUDA_MPS_IMAGE con il nome dell'immagine che hai creato per l'esempio cuda-mps.

    NVIDIA MPS richiede l'impostazione di hostIPC:true sui pod. La configurazione hostIPC:true consente al container di accedere alla risorsa host, il che introduce rischi per la sicurezza.

  3. Applica il manifest:

    kubectl apply -f cuda-mem-and-sm-count.yaml
    
  4. Controlla i log di questo pod:

    kubectl logs cuda-mem-and-sm-count
    

    In un esempio che utilizza NVIDIA Tesla L4 con gpu-sharing-strategy=mps e max-shared-clients-per-gpu=3, l'output è simile al seguente:

    For device 0:  Free memory: 7607 M, Total memory: 22491 M
    For device 0:  multiProcessorCount: 18
    

    In questo esempio, la GPU NVIDIA Tesla L4 ha 60 SM e 24 GB di memoria. Ogni unità di condivisione MPS riceve circa il 33% di thread attivi e 8 GB di memoria.

  5. Aggiorna il manifest per richiedere 2 nvidia.com/gpu:

      resources:
            limits:
              nvidia.com/gpu: 2
    

    L'output è simile al seguente:

    For device 0:  Free memory: 15230 M, Total memory: 22491 M
    For device 0:  multiProcessorCount: 38
    
  6. Aggiorna il manifest per eseguire l'override delle variabili CUDA_MPS_ACTIVE_THREAD_PERCENTAGE e CUDA_MPS_PINNED_DEVICE_MEM_LIMIT:

      env:
        - name: CUDA_MPS_ACTIVE_THREAD_PERCENTAGE
          value: "20"
        - name: CUDA_MPS_PINNED_DEVICE_MEM_LIMIT
          value: "0=8000M"
    

    L'output è simile al seguente:

    For device 0:  Free memory: 7952 M, Total memory: 22491 M
    For device 0:  multiProcessorCount: 10
    

Limitazioni

  • MPS sulle GPU pre-Volta (P100) ha funzionalità limitate rispetto ai tipi di GPU in e dopo Volta.
  • Con NVIDIA MPS, GKE garantisce che ogni container riceva una memoria del dispositivo bloccata e un thread attivo limitati. Tuttavia, altre risorse come la larghezza di banda della memoria, i codificatori o i decodificatori non vengono acquisite nell'ambito di questi limiti delle risorse. Di conseguenza, i container potrebbero influire negativamente sulle prestazioni di altri container se tutti richiedono la stessa risorsa illimitata.
  • NVIDIA MPS presenta limitazioni per la protezione della memoria e il contenimento degli errori . Ti consigliamo di valutare queste limitazioni per garantire la compatibilità con i tuoi carichi di lavoro.
  • NVIDIA MPS richiede l'impostazione di hostIPC:true sui pod. La configurazione hostIPC:true consente al container di accedere alla risorsa host, il che introduce rischi per la sicurezza.
  • GKE potrebbe rifiutare alcune richieste di GPU quando utilizzi NVIDIA MPS, per evitare comportamenti imprevisti durante l'allocazione della capacità.
  • Il numero massimo di container che possono condividere una singola GPU fisica con NVIDIA MPS è 48 (le GPU pre-Volta supportano solo 16). Quando pianifichi la configurazione di NVIDIA MPS, considera le esigenze di risorse dei tuoi workload e la capacità delle GPU fisiche sottostanti per ottimizzare le prestazioni e la reattività.

Passaggi successivi