GPUs mit NVIDIA MPS für mehrere Arbeitslasten freigeben


Auf dieser Seite erfahren Sie, wie Sie den Multi-Process-Dienst (MPS) von CUDA verwenden, damit mehrere Arbeitslasten einen einzelnen NVIDIA-GPU-Hardwarebeschleuniger in Ihrem GKE-Knoten (Google Kubernetes Engine) gemeinsam nutzen können.

Übersicht

NVIDIA MPS ist eine GPU-Freigabelösung, mit der mehrere Container eine einzelne physische NVIDIA-GPU-Hardware verwenden können, die an einen Knoten angehängt ist.

NVIDIA MPS stützt sich auf den Multi-Process-Dienst von NVIDIA auf CUDA. NVIDIA MPS ist eine alternative, binär kompatible Implementierung der CUDA API, die dafür entwickelt wurde, kooperative Multiprozess-CUDA-Anwendungen transparent für die gleichzeitige Ausführung auf einem einzelnen GPU-Gerät zu ermöglichen.

Mit NVIDIA MPS können Sie die maximal gemeinsam genutzten Container einer physischen GPU angeben. Mit diesem Wert wird festgelegt, wie viel der physischen GPU-Leistung jeder Container erhält. Dabei werden die folgenden Merkmale berücksichtigt:

Weitere Informationen zur Planung von GPUs mit NVIDIA MPS und der Verwendung von CUDA MPS finden Sie unter GPU-Freigabelösungen in GKE.

Zielgruppe dieses Leitfadens

Die Anleitung in diesem Abschnitt gilt für folgende Themen:

  • Plattformadministrator: Erstellt und verwaltet einen GKE-Cluster, plant Anforderungen für Infrastruktur und Ressourcen und überwacht die Leistung des Clusters.
  • Anwendungsentwickler: Entwirft Arbeitslasten in GKE-Clustern und stellt sie bereit. Eine Anleitung zum Anfordern von NVIDIA MPS mit GPUs finden Sie unter Arbeitslasten bereitstellen, die NVIDIA MPS mit GPUs verwenden.

Voraussetzungen

  • GKE-Version Sie können die GPU-Freigabe mit NVIDIA MPS in GKE Standard-Clustern mit GKE-Version 1.27.7-gke.1088000 und höher aktivieren.
  • GPU-Typ: Sie können NVIDIA MPS für alle NVIDIA Tesla®-GPU-Typen aktivieren.

Vorbereitung

Führen Sie die folgenden Schritte durch, bevor Sie beginnen:

  • Aktivieren Sie die Google Kubernetes Engine API.
  • Google Kubernetes Engine API aktivieren
  • Wenn Sie die Google Cloud CLI für diese Aufgabe verwenden möchten, müssen Sie die gcloud CLI installieren und dann initialisieren. Wenn Sie die gcloud CLI bereits installiert haben, rufen Sie die neueste Version mit gcloud components update ab.

NVIDIA MPS mit GPUs in GKE-Clustern aktivieren

Als Plattformadministrator müssen Sie NVIDIA MPS mit GPUs in einem GKE Standard-Cluster aktivieren. Anschließend können Anwendungsentwickler Arbeitslasten bereitstellen, um NVIDIA MPS mit GPUs zu verwenden. So aktivieren Sie NVIDIA MPS mit GPUs in GKE:

  1. NVIDIA MPS mit GPUs in einem neuen GKE-Cluster aktivieren
  2. NVIDIA-GPU-Gerätetreiber installieren (falls erforderlich)
  3. Prüfen Sie die GPU-Ressourcen, die auf Ihren Knoten verfügbar sind.

NVIDIA MPS mit GPUs in einem GKE-Cluster aktivieren

Sie können NVIDIA MPS mit GPUs aktivieren, wenn Sie GKE-Standardcluster erstellen. Diese Funktion ist im Standardknotenpool im Cluster aktiviert. NVIDIA MPS muss noch mit GPUs aktiviert werden, wenn Sie neue Knotenpools in diesem Cluster manuell erstellen.

Erstellen Sie über die Google Cloud CLI einen Cluster mit aktiviertem NVIDIA MPS:

gcloud container clusters create CLUSTER_NAME \
    --region=COMPUTE_REGION \
    --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

Ersetzen Sie dabei Folgendes:

  • CLUSTER_NAME: Der Name des neuen Clusters.
  • COMPUTE_REGION: die Compute Engine-Region für den neuen Cluster Geben Sie für zonale Cluster --zone=COMPUTE_ZONE an. Der verwendete GPU-Typ muss in der ausgewählten Zone verfügbar sein.
  • CLUSTER_VERSION ist die GKE-Version für die Steuerungsebene und die Knoten des Clusters. Verwenden Sie die GKE-Version 1.27.7-gke.1088000 oder höher. Alternativ können Sie mit dem Flag --release-channel=RELEASE_CHANNEL eine Release-Version mit dieser GKE-Version angeben.
  • MACHINE_TYPE ist der Compute Engine-Maschinentyp für Ihre Knoten.
  • GPU_TYPE ist der GPU-Typ, der eine NVIDIA Tesla-GPU-Plattform wie nvidia-tesla-v100 sein muss.
  • GPU_QUANTITY ist die Anzahl der physischen GPUs, die an jeden Knoten im Standardknotenpool angehängt werden.
  • CLIENTS_PER_GPU ist die maximale Anzahl von Containern, die jede physische GPU gemeinsam nutzen können.
  • DRIVER_VERSION: die zu installierende NVIDIA-Treiberversion. Kann eines der Folgenden sein:
    • default: Installieren Sie die Standardtreiberversion für Ihre GKE-Version.
    • latest: Installieren Sie die neueste verfügbare Treiberversion für Ihre GKE-Version. Nur für Knoten verfügbar, die Container-Optimized OS verwenden.
    • disabled: Automatische Treiberinstallation überspringen. Sie müssen einen Treiber manuell installieren, nachdem Sie den Knotenpool erstellt haben. Wenn Sie gpu-driver-version weglassen, ist dies die Standardoption.

NVIDIA MPS mit GPUs in einem neuen Knotenpool aktivieren

Sie können NVIDIA MPS mit GPUs aktivieren, wenn Sie neue Knotenpools in einem GKE-Cluster manuell erstellen. Erstellen Sie über die Google Cloud CLI einen Knotenpool mit aktiviertem NVIDIA MPS:

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

Ersetzen Sie dabei Folgendes:

  • NODEPOOL_NAME ist der Name des neuen Knotenpools.
  • CLUSTER_NAME ist der Name Ihres Clusters, auf dem die GKE-Version 1.27.7-gke.1088000 oder höher ausgeführt werden muss.
  • COMPUTE_REGION ist die Compute Engine-Region des Clusters. Geben Sie für zonale Cluster --zone=COMPUTE_ZONE an.
  • MACHINE_TYPE ist der Compute Engine-Maschinentyp für Ihre Knoten. Verwenden Sie für A100-GPUs einen A2-Maschinentyp. Verwenden Sie für alle anderen GPUs einen N1-Maschinentyp.
  • GPU_TYPE ist der GPU-Typ, der eine NVIDIA Tesla-GPU-Plattform wie nvidia-tesla-v100 sein muss.
  • GPU_QUANTITY ist die Anzahl der physischen GPUs, die an jeden Knoten im Knotenpool angehängt werden sollen.
  • CONTAINER_PER_GPU ist die maximale Anzahl von Containern, die jede physische GPU gemeinsam nutzen können.
  • DRIVER_VERSION: die zu installierende NVIDIA-Treiberversion. folgende Arten von Werten sind möglich:

    • default: Installieren Sie die Standardtreiberversion für Ihre GKE-Version.
    • latest: Installieren Sie die neueste verfügbare Treiberversion für Ihre GKE-Version. Nur für Knoten verfügbar, die Container-Optimized OS verwenden.
    • disabled: Automatische Treiberinstallation überspringen. Sie müssen einen Treiber manuell installieren, nachdem Sie den Knotenpool erstellt haben. Wenn Sie gpu-driver-version weglassen, ist dies die Standardoption.

NVIDIA-GPU-Gerätetreiber installieren

Wenn Sie bei der Erstellung des Clusters die automatische Treiberinstallation deaktiviert haben oder wenn Sie eine GKE-Version vor 1.27.2-gke.1200 verwenden, müssen Sie manuell einen kompatiblen NVIDIA-Treiber installieren, der die NVIDIA MPS-Division der physischen GPUs verwaltet. Zum Installieren der Treiber stellen Sie ein GKE-Installations-DaemonSet bereit, das die Treiber einrichtet.

Eine Anleitung finden Sie unter NVIDIA-GPU-Gerätetreiber installieren.

Verfügbare GPU-Ressourcen prüfen

Sie können prüfen, ob die Anzahl der GPUs in Ihren Knoten mit der Anzahl übereinstimmt, die Sie bei der Aktivierung von NVIDIA MPS angegeben haben. Sie können auch prüfen, ob der NVIDIA MPS-Steuerungs-Daemon ausgeführt wird.

Prüfen Sie die auf Ihren Knoten verfügbaren GPU-Ressourcen

Mit folgendem Befehl können Sie die auf Ihren Knoten verfügbaren GPU-Ressourcen prüfen:

kubectl describe nodes NODE_NAME

Ersetzen Sie NODE_NAME durch Ihren Ingress-Namen.

Die Ausgabe sieht in etwa so aus:

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

In dieser Ausgabe beträgt die Anzahl der GPU-Ressourcen auf dem Knoten 3 aufgrund der folgenden Werte:

  • Der Wert in max-shared-clients-per-gpu ist 3.
  • Die count der physischen GPUs, die dem Knoten hinzugefügt werden sollen, ist 1. Wenn die count der physischen GPUs 2 wäre, würde die Ausgabe 6 zuweisbare GPU-Ressourcen anzeigen, drei pro jeder physischen GPU.

Ausführung des MPS-Kontroll-Daemon prüfen

Das GPU-Geräte-Plug-in führt eine Systemdiagnose für den MPS-Steuerungs-Daemon durch. Wenn der MPS-Kontroll-Daemon fehlerfrei ist, können Sie einen Container bereitstellen.

Führen Sie folgenden Befehl aus, um den MPS-Status zu prüfen:

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

Die Ausgabe sieht in etwa so aus:

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
...

In der Ausgabe sehen Sie möglicherweise, dass die folgenden Ereignisse aufgetreten sind:

  • Der Fehler failed to start GPU device manager steht vor dem Fehler MPS is healthy. Dieser Fehler ist nur vorübergehend. Wenn die Meldung MPS is healthy angezeigt wird, wird der Kontroll-Daemon ausgeführt.
  • Die Nachricht active thread percentage = 100.0 bedeutet, dass die gesamte physische GPU-Ressource einen vollständig aktiven Thread hat.

Arbeitslasten bereitstellen, die MPS verwenden

Als Anwendungsoperator, der GPU-Arbeitslasten bereitstellt, können Sie GKE anweisen, MPS-Freigabeeinheiten in derselben physischen GPU freizugeben. Im folgenden Manifest fordern Sie eine physische GPU an und legen max-shared-clients-per-gpu=3 fest. Die physische GPU erhält drei MPS-Freigabeeinheiten und startet einen nvidia/samples:nbody-Job mit drei Pods (Containern), die parallel ausgeführt werden.

  1. Speichern Sie das Manifest als 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 diesem Manifest:

    • hostIPC: true ermöglicht Pods, mit dem MPS-Kontroll-Daemon zu kommunizieren. Er ist erforderlich. Beachten Sie jedoch, dass die hostIPC: true-Konfiguration dem Container Zugriff auf die Hostressource ermöglicht, was Sicherheitsrisiken mit sich bringt.
    • 5.000 Iterationen werden im Benchmarkmodus ausgeführt.
  2. Wenden Sie das Manifest an:

    kubectl apply -f gpu-mps.yaml
    
  3. Prüfen Sie, ob alle Pods ausgeführt werden:

    kubectl get pods
    

    Die Ausgabe sieht in etwa so aus:

    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. Überprüfen Sie die Logs der Pods, um festzustellen, ob der Job abgeschlossen wurde:

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

    Die Ausgabe sieht in etwa so aus:

    ...
    > 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
    ...
    

    Da GKE 50.000 Iterationen ausführt, kann das Log einige Minuten dauern.

Bereinigen

Löschen Sie die Jobs und alle zugehörigen Pods mit dem folgenden Befehl:

kubectl delete job --all

Angepinnten Gerätespeicher und aktiven Thread mit NVIDIA MPS beschränken

Wenn Sie eine GPU mit NVIDIA MPS in GKE verwenden, werden standardmäßig die folgenden CUDA-Umgebungsvariablen in die GPU-Arbeitslast eingefügt:

  • CUDA_MPS_ACTIVE_THREAD_PERCENTAGE: Diese Variable gibt den Prozentsatz der verfügbaren Threads an, die jede MPS-Freigabeeinheit verwenden kann. Standardmäßig ist jede MPS-Freigabeeinheit der GPU auf 100 / MaxSharedClientsPerGPU gesetzt, um einen gleichen Teil der GPU-Berechnung in Bezug auf den Stream-Multiprozessor zu erhalten.
  • CUDA_MPS_PINNED_DEVICE_MEM_LIMIT: Diese Variable begrenzt die Größe des GPU-Speichers, der von einer MPS-Freigabeeinheit der GPU zugewiesen werden kann. Standardmäßig ist jede MPS-Freigabeeinheit der GPU auf total mem / MaxSharedClientsPerGPU gesetzt, um ein gleiches Segment des GPU-Arbeitsspeichers zu erhalten.

Konfigurieren Sie diese NVIDIA MPS-Umgebungsvariablen, um ein Ressourcenlimit für Ihre GPU-Arbeitslasten festzulegen:

  1. Prüfen und erstellen Sie das Image des cuda-mps-Beispiels in GitHub.

  2. Speichern Sie das folgende Manifest als 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
    

    Ersetzen Sie CUDA_MPS_IMAGE durch den Namen des Images, das Sie für das Beispiel cuda-mps erstellt haben.

    Für NVIDIA MPS muss auf Pods hostIPC:true festgelegt werden. Die hostIPC:true-Konfiguration ermöglicht einem Container den Zugriff auf die Hostressource, was Sicherheitsrisiken mit sich bringt.

  3. Wenden Sie das Manifest an:

    kubectl apply -f cuda-mem-and-sm-count.yaml
    
  4. Prüfen Sie die Logs für diesen Pod:

    kubectl logs cuda-mem-and-sm-count
    

    In einem Beispiel, in dem NVIDIA Tesla® L4 mit gpu-sharing-strategy=mps und max-shared-clients-per-gpu=3 verwendet wird, sieht die Ausgabe etwa so aus:

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

    In diesem Beispiel hat die NVIDIA Tesla® L4-GPU 60 SM und 24 GB Arbeitsspeicher. Jede MPS-Freigabeeinheit erhält etwa 33% aktiven Thread und 8 GB Arbeitsspeicher.

  5. Aktualisieren Sie das Manifest, um 2 nvidia.com/gpu anzufordern:

      resources:
            limits:
              nvidia.com/gpu: 2
    

    Die Ausgabe sieht in etwa so aus:

    For device 0:  Free memory: 15230 M, Total memory: 22491 M
    For device 0:  multiProcessorCount: 38
    
  6. Aktualisieren Sie das Manifest, um die Variablen CUDA_MPS_ACTIVE_THREAD_PERCENTAGE und CUDA_MPS_PINNED_DEVICE_MEM_LIMIT zu überschreiben:

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

    Die Ausgabe sieht in etwa so aus:

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

Beschränkungen

  • MPS auf Pre-Volta-GPUs (P100) hat im Vergleich zu GPU-Typen in und nach Volta eingeschränkte Funktionen.
  • Mit NVIDIA MPS sorgt GKE dafür, dass jeder Container einen begrenzten Gerätespeicher und aktiven Thread erhält. Andere Ressourcen wie Speicherbandbreite, Encoder oder Decodierer werden jedoch nicht als Teil dieser Ressourcenlimits erfasst. Dies kann dazu führen, dass sich Container negativ auf die Leistung anderer Container auswirken, wenn sie alle dieselbe unbegrenzte Ressource anfordern.
  • NVIDIA MPS hat Einschränkungen für den Speicherschutz und die Fehlereindämmung. Wir empfehlen Ihnen, diese Einschränkungen zu prüfen, um die Kompatibilität mit Ihren Arbeitslasten zu gewährleisten.
  • Für NVIDIA MPS muss auf Pods hostIPC:true festgelegt werden. Die hostIPC:true-Konfiguration ermöglicht einem Container den Zugriff auf die Hostressource, was Sicherheitsrisiken mit sich bringt.
  • GKE kann bei der Verwendung von NVIDIA MPS bestimmte GPU-Anfragen ablehnen, um unerwartetes Verhalten während der Kapazitätszuweisung zu verhindern. Weitere Informationen finden Sie unter Anfragelimits für GPU-Freigabelösungen.
  • Die maximale Anzahl von Containern, die eine einzelne physische GPU mit NVIDIA MPS gemeinsam nutzen können, beträgt 48 (Pre-Volta-GPU unterstützt nur 16). Berücksichtigen Sie bei der Planung der NVIDIA MPS-Konfiguration den Ressourcenbedarf Ihrer Arbeitslasten und die Kapazität der zugrunde liegenden physischen GPUs, um die Leistung und die Reaktionsfähigkeit zu optimieren.
  • Die NVIDIA MPS API-Konfiguration wird nur über die Google Cloud CLI oder die Google Cloud Console unterstützt.

Nächste Schritte