Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.
Berechnung und Autoscaling
Tipp
Registrieren Sie sich
GPU-Ressourcenoptimierung und Kostenmanagement
Planen Sie Workloads anhand von GPU-Anforderungen mithilfe von Labels Well-Known
Für AI/ML Workloads, die auf unterschiedliche GPU-Eigenschaften reagieren (z. B. GPU, GPU-Speicher), empfehlen wir, die GPU-Anforderungen mithilfe bekannter Scheduling-Labels zu spezifizieren, die von den in Karpenter verwendeten Knotentypen
Beispiel
Verwenden Sie beispielsweise den Knotenselektor für den GPU-Namen, wenn Sie Karpenter verwenden:
apiVersion: v1 kind: Pod metadata: name: gpu-pod-example spec: containers: - name: ml-workload image: <image> resources: limits: nvidia.com/gpu: 1 # Request one NVIDIA GPU nodeSelector: karpenter.k8s.aws/instance-gpu-name: "l40s" # Run on nodes with NVIDIA L40S GPUs
Verwenden Sie das Kubernetes Device Plugin, um GPUs verfügbar zu machen
Um GPUs auf Knoten verfügbar zu machen, muss der NVIDIA-GPU-Treiber auf dem Betriebssystem des Knotens installiert und die Container-Runtime so konfiguriert sein, dass der Kubernetes-Scheduler Knoten mit verfügbaren GPUs Pods zuweisen kann. Der Einrichtungsvorgang für das NVIDIA Kubernetes Device Plugin hängt vom verwendeten EKS Accelerated AMI ab:
-
Bottlerocket Accelerated AMI : Dieses AMI enthält den NVIDIA-GPU-Treiber und das NVIDIA Kubernetes Device Plugin
ist vorinstalliert und einsatzbereit, sodass die GPU-Unterstützung sofort einsatzbereit ist. Es ist keine zusätzliche Konfiguration erforderlich, um GPUs für den Kubernetes-Scheduler verfügbar zu machen. -
AL2023 Accelerated AMI
: Dieses AMI beinhaltet den NVIDIA-GPU-Treiber, aber das NVIDIA Kubernetes Device Plugin ist nicht vorinstalliert. Sie müssen das Geräte-Plugin separat installieren und konfigurieren, in der Regel über eine. DaemonSet Beachten Sie, dass, wenn Sie eksctl verwenden, um Ihren Cluster zu erstellen und einen GPU-Instance-Typ (z. B. g5.xlarge) in Ihrem angeben ClusterConfig,eksctlautomatisch das entsprechende AMI ausgewählt und das NVIDIA Kubernetes Device Plugin installiert wird. Weitere Informationen finden Sie unter GPU-Unterstützungin der eksctl-Dokumentation.
Wenn Sie sich dafür entscheiden, stattdessen die EKS Accelerated AMIs und den NVIDIA GPU-Operator
Führen Sie Folgendes aus, um zu überprüfen, ob das NVIDIA-Geräte-Plug-In aktiv ist und die GPUs korrekt verfügbar sind:
kubectl describe node | grep nvidia.com/gpu
Mit diesem Befehl wird überprüft, ob die nvidia.com/gpu Ressource die Kapazität und die zuweisbaren Ressourcen des Knotens erfüllt. Beispielsweise sollte ein Knoten mit einer GPU angezeigt werden. nvidia.com/gpu: 1 Weitere Informationen finden Sie im Kubernetes GPU Scheduling Guide
Verwenden Sie viele verschiedene EC2-Instance-Typen
Die Verwendung so vieler verschiedener EC2-Instance-Typen wie möglich ist eine wichtige bewährte Methode für die Skalierbarkeit auf Amazon EKS, wie im Kubernetes-Datenebene Abschnitt beschrieben. Diese Empfehlung gilt auch für Instances mit beschleunigter Hardware (z. B. GPUs). Wenn Sie einen Cluster erstellen, der nur einen Instance-Typ verwendet, und versuchen, die Anzahl der Knoten über die Kapazität der Region hinaus zu skalieren, erhalten Sie möglicherweise einen Fehler wegen unzureichender Kapazität (ICE), der darauf hinweist, dass keine Instances verfügbar sind. Es ist wichtig, die einzigartigen Merkmale Ihrer AI/ML Workloads zu verstehen, bevor Sie sie beliebig diversifizieren. Überprüfen Sie die verfügbaren Instance-Typen mithilfe des Tools
Instances für beschleunigte Datenverarbeitung werden in verschiedenen Kaufmodellen angeboten, um kurzfristigen, mittelfristigen und stationären Workloads gerecht zu werden. Für kurzfristige, flexible und fehlertolerante Workloads, bei denen Sie eine Reservierung vermeiden möchten, sollten Sie sich Spot-Instances ansehen. Mit Kapazitätsblöcken, On-Demand Instances und Sparplänen können Sie beschleunigte Recheninstanzen für mittel- und langfristige Workloads bereitstellen. Um die Chancen zu erhöhen, dass Sie mit Ihrer bevorzugten Kaufoption erfolgreich auf die benötigte Kapazität zugreifen, wird empfohlen, eine vielfältige Liste von Instanztypen und Verfügbarkeitszonen zu verwenden. Wenn Sie auf ICEs für ein bestimmtes Kaufmodell stoßen, versuchen Sie es alternativ erneut, ein anderes Modell zu verwenden.
Beispiel Das folgende Beispiel zeigt, wie ein Karpenter in die Lage versetzt wird NodePool , G- und P-Instances bereitzustellen, die älter als Generation 3 sind (z. B. p3). Weitere Informationen finden Sie im Bewährte Methoden zur EKS-Skalierbarkeit Abschnitt.
- key: karpenter.k8s.aws/instance-category operator: In values: ["g", "p"] # Diversifies across G-series and P-series - key: karpenter.k8s.aws/instance-generation operator: Gt values: ["3"] # Selects instance generations greater than 3
Einzelheiten zur Verwendung von Spot-Instances für GPUs finden Sie weiter unten unter „Erwägen Sie die Verwendung von Amazon EC2 Spot-Instances für GPUs mit Karpenter“.
Erwägen Sie die Verwendung von Amazon EC2 Spot-Instances für GPUs mit Karpenter
Mit Amazon EC2 Spot-Instances können Sie ungenutzte EC2-Kapazitäten in der AWS-Cloud nutzen. Sie sind mit einem Rabatt von bis zu 90% im Vergleich zu den Preisen erhältlich. On-Demand Amazon EC2 Spot-Instances können mit einer Frist von zwei Minuten unterbrochen werden, wenn EC2 die Kapazität wieder benötigt. Weitere Informationen finden Sie unter Spot-Instances im Amazon EC2-Benutzerhandbuch. Amazon EC2 Spot kann eine hervorragende Wahl für fehlertolerante, statusfreie und flexible (Zeit und Instance-Typ) Workloads sein. Weitere Informationen darüber, wann Spot-Instances verwendet werden sollten, finden Sie unter Best Practices für EC2 Spot-Instances. Sie können Spot-Instances auch für AI/ML Workloads verwenden, wenn dies der Fall ist. Spot-friendly
Anwendungsfälle
Spot-friendly Bei Workloads kann es sich um Big Data, containerisierte Workloads, statusfreie Webserver CI/CD, High Performance Computing (HPC) und Rendering-Workloads handeln. Spot-Instances eignen sich nicht für Workloads, die unflexibel, statusbehaftet, fehlerintolerant oder eng zwischen Instance-Knoten gekoppelt sind (z. B. Workloads mit parallelen Prozessen, die bei der Berechnung stark voneinander abhängen und eine ständige Kommunikation zwischen den Knoten erfordern, wie z. B. MPI-based Hochleistungsrechneranwendungen wie Computational Fluid Dynamics oder verteilte Datenbanken mit komplexen Interdependenzen). Hier sind die spezifischen Anwendungsfälle, die wir empfehlen (in keiner bestimmten Reihenfolge):
-
Real-time Online-Inferenz: Verwenden Sie Spot-Instances für eine kostenoptimierte Skalierung Ihrer Echtzeit-Inferenz-Workloads, sofern Ihre Workloads Spot-freundlich sind. Mit anderen Worten, die Inferenzzeit beträgt entweder weniger als zwei Minuten, die Anwendung ist fehlertolerant gegenüber Unterbrechungen und kann auf verschiedenen Instance-Typen ausgeführt werden. Stellen Sie eine hohe Verfügbarkeit durch Instanzvielfalt (z. B. über mehrere Instance-Typen und Availability Zones) oder Reservierungen sicher und implementieren Sie gleichzeitig Fehlertoleranz auf Anwendungsebene, um potenzielle Spot-Unterbrechungen zu bewältigen.
-
Hyper-parameter Tuning: Verwenden Sie Spot-Instances, um explorative Tuning-Jobs opportunistisch auszuführen, da Unterbrechungen ohne nennenswerten Verlust toleriert werden können, insbesondere bei kurzzeitigen Experimenten.
-
Datenerweiterung: Verwenden Sie Spot-Instances, um Datenvorverarbeitungs- und Augmentierungsaufgaben durchzuführen, die bei einer Unterbrechung von Checkpoints aus neu gestartet werden können. Somit eignen sie sich ideal für die variable Verfügbarkeit von Spot.
-
Fine-tuning Modelle: Verwenden Sie Spot-Instances für die Feinabstimmung mit robusten Checkpoint-Mechanismen, um vom zuletzt gespeicherten Zustand aus fortzufahren und so die Auswirkungen von Instance-Unterbrechungen zu minimieren.
-
Batch-Inferenz: Verwenden Sie Spot-Instances, um große Stapel von Offline-Inferenzanforderungen ohne Echtzeitzugriff zu verarbeiten. Dabei können Jobs unterbrochen und wieder aufgenommen werden. So können Sie die Kosteneinsparungen von Spot optimal nutzen und potenzielle Unterbrechungen durch Wiederholungen oder Diversifizierung bewältigen.
-
Opportunistische Trainingsuntergruppen: Verwenden Sie Spot-Instances für marginale oder experimentelle Trainingsworkloads (z. B. kleinere Modelle mit weniger als 10 Millionen Parametern), bei denen Unterbrechungen akzeptabel sind und Effizienzoptimierungen wie eine Diversifizierung zwischen Instanztypen oder Regionen angewendet werden können. Dies wird jedoch aufgrund potenzieller Unterbrechungen nicht für Schulungen im Produktionsumfang empfohlen.
Überlegungen
Um Spot-Instances für beschleunigte Workloads auf Amazon EKS zu verwenden, sind eine Reihe wichtiger Überlegungen (in keiner bestimmten Reihenfolge) zu berücksichtigen:
-
Verwenden Sie Karpenter, um Spot-Instances mit aktivierter erweiterter Konsolidierung zu verwalten. Durch Angabe von Karpenter. sh/capacityWenn Sie in Ihrem Karpenter „spot“ eingeben NodePool, stellt Karpenter standardmäßig Spot-Instances ohne zusätzliche Konfiguration bereit. Um jedoch eine erweiterte Spot-to-Spot Konsolidierung zu ermöglichen, bei der nicht ausgelastete Spot-Knoten durch günstigere Spot-Alternativen ersetzt werden, müssen Sie das Feature-Gate aktivieren, indem Sie --feature-gates SpotToSpotConsolidation =true in den SpotToSpotConsolidation Controller-Argumenten
von Karpenter oder über die Umgebungsvariable FEATURE_GATES setzen. Karpenter verwendet für die Bereitstellung von EC2-Instances die Strategie der preis-/kapazitätsoptimierten Zuweisung. https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-fleet-allocation-strategy.html Basierend auf den NodePool Anforderungen und Pod-Einschränkungen packt Karpenter unplanbare Pods in Bin-Packs und sendet eine Vielzahl von Instance-Typen an die Amazon EC2 Fleet API. https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-fleet-request-type.html Sie können das EC2 Instance Type Explorer-Tool verwenden, um eine Liste von Instance-Typen zu generieren, die Ihren spezifischen Rechenanforderungen entsprechen. -
Stellen Sie sicher, dass Workloads statusfrei, fehlertolerant und flexibel sind. Workloads müssen statusfrei, fehlertolerant und hinsichtlich ihrer Größe flexibel sein. instance/GPU Dies ermöglicht eine reibungslose Wiederaufnahme nach Spot-Unterbrechungen, und die Flexibilität der Instance ermöglicht es Ihnen, möglicherweise länger auf Spot zu bleiben. Aktivieren Sie die Behandlung von Spot-Unterbrechungen
in Karpenter, indem Sie den Helm-Wert settings.interruptionQueue mit dem Namen der AWS SQS-Warteschlange konfigurieren, um Spot-Unterbrechungen abzufangen. Verwenden Sie beispielsweise bei der Installation über Helm --set „settings.interruptionQueue=$ {CLUSTER_NAME}“. Ein Beispiel finden Sie im Handbuch Erste Schritte mit Karpenter. https://karpenter.sh/docs/getting-started/getting-started-with-karpenter/ Wenn Karpenter ein Spot-Unterbrechungsereignis bemerkt, sperrt es die Knoten automatisch ab, verunreinigt, entleert und schließt sie vor dem Unterbrechungsereignis, um die Übergangszeit der Pods zu maximieren. Gleichzeitig startet Karpenter sofort einen neuen Knoten, damit dieser so schnell wie möglich einsatzbereit ist. -
Vermeiden Sie es, die Auswahl des Instanztyps zu stark einzuschränken. Sie sollten es so weit wie möglich vermeiden, die Instanztypen einzuschränken. Wenn Sie die Instance-Typen nicht einschränken, besteht eine höhere Wahrscheinlichkeit, Spot-Kapazität in großem Umfang mit einer geringeren Häufigkeit von Spot-Instance-Unterbrechungen zu geringeren Kosten zu erwerben. Vermeiden Sie es beispielsweise, sich auf bestimmte Typen zu beschränken (z. B. g5.xlarge). Erwägen Sie, mithilfe von Schlüsseln wie karpenter.k8s eine Vielzahl von Instanzkategorien und -generationen anzugeben. aws/instance-category und karpenter.k8s. aws/instance-Generation. Karpenter ermöglicht eine einfachere Diversifizierung der On-Demand- und Spot-Instance-Kapazität über mehrere Instance-Typen und Availability Zones (AZs) hinweg. Darüber hinaus können Sie Spot Placement Score verwenden, um vor dem Start dynamisch die optimale Region für die Bereitstellung Ihres AI/ML Workloads zu ermitteln, wenn Ihr Workload eine bestimmte oder eine begrenzte Anzahl von Beschleunigern erfordert, aber zwischen den Regionen flexibel ist.
-
Erweitern Sie die NodePool Anforderungen, um eine größere Anzahl ähnlicher EC2-Instance-Familien einzubeziehen. Jeder Spot-Instance-Pool besteht aus einer ungenutzten EC2-Instance-Kapazität für einen bestimmten Instance-Typ in einer bestimmten Availability Zone (AZ). Wenn Karpenter versucht, einen neuen Knoten bereitzustellen, wählt es einen Instance-Typ aus, der den NodePool Anforderungen von Karpenter entspricht. Wenn in keinem AZ ein kompatibler Instanztyp über Spot-Kapazität verfügt, schlägt die Bereitstellung fehl. Um dieses Problem zu vermeiden, sollten Sie umfassendere Instances der G-Serie (Generation 4 oder höher) von NVIDIA in verschiedenen Größen und Availability Zones (AZs) zulassen und gleichzeitig Hardwareanforderungen wie GPU-Speicher oder Raytracing berücksichtigen. Da es sich um verschiedene Typen von Instances handeln kann, müssen Sie sicherstellen, dass Ihre Workload auf jedem Typ ausgeführt werden kann und dass die Leistung, die Sie erhalten, Ihren Anforderungen entspricht.
-
Nutzen Sie alle Verfügbarkeitszonen in einer Region. Die verfügbare Kapazität variiert je nach Availability Zone (AZ). Ein bestimmter Instance-Typ ist in einer AZ möglicherweise nicht verfügbar, in einer anderen jedoch reichlich. Jede einzigartige Kombination aus einem Instance-Typ und einer Availability Zone bildet einen separaten Spot-Kapazitätspool. Indem Sie Kapazität für alle AZs in einer Region anfordern, die Ihren NodePool Karpenter-Anforderungen entspricht, durchsuchen Sie effektiv mehrere Pools gleichzeitig. Dadurch wird die Anzahl der Spot-Kapazitätspools maximiert und somit die Wahrscheinlichkeit, Spot-Kapazität zu erwerben, erhöht. Um dies zu erreichen, lassen Sie in Ihrer NodePool Konfiguration entweder topology.kubernetes weg. io/zone Geben Sie die Taste vollständig ein, damit Karpenter aus allen verfügbaren AZs in der Region auswählen kann, oder listen Sie die AZs explizit auf, indem Sie den Operator: In verwenden und die Werte angeben (z. B. us-west-2a).
-
Erwägen Sie, den Spot Placement Score (SPS) zu verwenden, um einen Überblick über die Wahrscheinlichkeit zu erhalten, mit Spot-Instances erfolgreich auf die erforderliche Kapazität zuzugreifen. Der Spot Placement Score (SPS) ist ein Tool, das Ihnen anhand einer Bewertung hilft, einzuschätzen, wie wahrscheinlich es ist, dass eine Spot-Anfrage erfolgreich ist. Wenn Sie SPS verwenden, geben Sie zuerst Ihre Rechenanforderungen für Ihre Spot-Instances an, und dann gibt Amazon EC2 die 10 wichtigsten Regionen oder Availability Zones (AZs) zurück, in denen Ihre Spot-Anfrage wahrscheinlich erfolgreich sein wird. Regionen und Availability Zones werden auf einer Skala von 1 bis 10 bewertet. Ein Wert von 10 gibt an, dass Ihre Spot-Anfrage sehr wahrscheinlich, aber nicht garantiert erfolgreich ist. Ein Ergebnis von 1 zeigt an, dass Ihre Spot-Anforderung sehr wahrscheinlich nicht erfolgreich sein wird. Dasselbe Ergebnis kann für verschiedene Regionen oder Availability Zones zurückgegeben werden. Weitere Informationen finden Sie unter Anleitung zum Erstellen eines Spot Placement Score Tracker-Dashboards auf AWS. Da die Spot-Kapazität ständig schwankt, hilft Ihnen SPS dabei, herauszufinden, welche Kombination aus Instance-Typen, AZs und Regionen für Ihre Workload-Einschränkungen (d. h. Flexibilität, Leistung, Größe usw.) am besten geeignet ist. Wenn Ihr AI/ML Workload bestimmte oder eine begrenzte Anzahl von Beschleunigern erfordert, aber zwischen den Regionen flexibel ist, können Sie den Spot Placement Score verwenden, um vor dem Start dynamisch die optimale Region für die Bereitstellung Ihres Workloads zu ermitteln. Damit Sie die Wahrscheinlichkeit, Spot-Kapazität zu erwerben, automatisch ermitteln können, stellen wir Ihnen eine Anleitung zur Erstellung eines SPS-Tracker-Dashboards zur Verfügung. Diese Lösung überwacht die SPS-Ergebnisse im Zeitverlauf mithilfe einer YAML-Konfiguration für unterschiedliche Setups (z. B. Instance-Anforderungen einschließlich GPUs), speichert Metriken darin und stellt Dashboards zum Vergleich von Konfigurationen CloudWatch bereit. Definieren Sie Dashboards pro Workload, um die vCPU-, Speicher- und GPU-Anforderungen zu bewerten und so optimale Setups für EKS-Cluster sicherzustellen, einschließlich der Berücksichtigung der Verwendung anderer AWS-Regionen. Weitere Informationen finden Sie unter So funktioniert der Spot-Placement-Score.
-
Gehen Sie sorgsam mit Spot-Unterbrechungen um und testen Sie. Bei einem Pod mit einer Kündigungsfrist von mehr als zwei Minuten wird der alte Knoten unterbrochen, bevor diese Pods neu geplant werden, was sich auf die Verfügbarkeit der Workloads auswirken kann. Berücksichtigen Sie beim Entwerfen Ihrer Anwendungen den zweiminütigen Spot-Unterbrechungshinweis, implementieren Sie Checkpoints in lang laufenden Anwendungen (z. B. Speichern des Fortschritts in einem persistenten Speicher wie Amazon S3), um sie nach Unterbrechungen fortzusetzen, verlängern Sie die Beendigung GracePeriodSeconds (Standard ist 30 Sekunden) in den Pod-Spezifikationen, um mehr Zeit für ein ordnungsgemäßes Herunterfahren zu haben, und behandeln Sie Unterbrechungen mithilfe von PreStop-Lifecycle-Hooks and/or SIGTERM-Signale in Ihrer Anwendung für ordnungsgemäßes Herunterfahren wie Bereinigen, Speichern des Status und Schließen der Verbindung. Bei Echtzeit-Workloads, bei denen die Skalierungszeit wichtig ist und Workloads länger als zwei Minuten dauern, bis die Anwendung bereit ist, den Traffic zu verarbeiten, sollten Sie erwägen, die Startzeiten von Containern und ML-Modellen durch Überprüfung Speicher und Skalierung und Leistung von Anwendungen Best Practices zu optimieren. Um einen Ersatzknoten zu testen, verwenden Sie den AWS Fault Injection Service
(FIS), um Spot-Unterbrechungen zu simulieren.
Zusätzlich zu diesen bewährten Kernmethoden für Spot sollten Sie diese Faktoren bei der Verwaltung von GPU-Workloads auf Amazon EKS berücksichtigen. Im Gegensatz zu CPU-based Workloads reagieren GPU-Workloads besonders empfindlich auf Hardwaredetails wie GPU-Funktionen und verfügbaren GPU-Speicher. GPU-Workloads sind möglicherweise durch die Instance-Typen, die sie verwenden können, eingeschränkt, sodass im Vergleich zu CPUs weniger Optionen verfügbar sind. Prüfen Sie zunächst, ob Ihre Arbeitslast instanzflexibel ist. Wenn Sie nicht wissen, wie viele Instance-Typen Ihr Workload verwenden kann, testen Sie sie einzeln, um Kompatibilität und Funktionalität sicherzustellen. Identifizieren Sie, wie flexibel Sie sein können, um so viel wie möglich zu diversifizieren, und stellen Sie gleichzeitig sicher, dass die Arbeitslast durch Diversifizierung am Laufen bleibt, und verstehen Sie alle Auswirkungen auf die Leistung (z. B. auf den Durchsatz oder die Abschlusszeit). Beachten Sie bei der Diversifizierung Ihrer Workloads Folgendes:
-
Überprüfen Sie die CUDA- und Framework-Kompatibilität. Ihre GPU-Workloads sind möglicherweise für bestimmte Hardware, GPU-Typen (z. B. V100 in P3 gegenüber A100 in P4) optimiert oder für bestimmte CUDA-Versionen für Bibliotheken wie TensorFlow geschrieben. Überprüfen Sie daher unbedingt die Kompatibilität für Ihre Workloads. Diese Kompatibilität ist entscheidend, um Laufzeitfehler, Abstürze, Ausfälle bei der GPU-Beschleunigung (z. B. nicht übereinstimmende CUDA-Versionen mit Frameworks wie PyTorch oder TensorFlow können die Ausführung verhindern) oder um Hardwarefunktionen wie Präzision nutzen zu können. FP16/INT8
-
GPU-Speicher. Stellen Sie sicher, dass Sie die Speicheranforderungen Ihrer Modelle auswerten und die Speichernutzung Ihres Modells während der Laufzeit mithilfe von Tools wie dem DCGM-Exporter
profilieren. Stellen Sie den minimalen GPU-Speicher ein, der für den Instance-Typ erforderlich ist, in bekannten Labels wie karpenter.k8s. aws/instance-gpu-speicher. GPU-VRAM variiert je nach Instance-Typ (z. B. NVIDIA T4 hat 16 GB, A10G hat 24 GB, V100 hat 16-32 GB), und ML-Modelle (z. B. große Sprachmodelle) können den verfügbaren Speicher überschreiten, was zu OOM-Fehlern oder Abstürzen führen kann. Bei Spot-Instances in EKS kann dies die Diversifizierung einschränken. Beispielsweise können Sie keine Typen mit niedrigerem VRAM einbeziehen, wenn Ihr Modell nicht passt. Dadurch kann der Zugriff auf Kapazitätspools eingeschränkt und das Unterbrechungsrisiko erhöht werden. Beachten Sie, dass bei Inferenz mit einer einzelnen GPU und einem Knoten (z. B. mehrere Pods, die auf demselben Knoten geplant sind, um dessen GPU-Ressourcen zu nutzen) die Diversifizierung einschränken kann, da Sie nur Instance-Typen mit ausreichend VRAM in Ihre Spot-Konfiguration aufnehmen können. -
Floating-point Präzision und Leistung. Nicht alle Nvidia-GPU-Architekturen haben die gleiche Gleitkommagenauigkeit (z. B. FP16/INT8). Bewerten Sie die Leistung der Kerntypen (CUDA/Tensor/RT) und die Gleitkommagenauigkeit, die für Ihre Workloads erforderlich sind. Wenn Sie auf einer preisgünstigeren, leistungsschwächeren GPU arbeiten, bedeutet das nicht, dass sie besser ist. Sie sollten also erwägen, die Leistung anhand der innerhalb eines bestimmten Zeitrahmens abgeschlossenen Arbeit zu bewerten, um die Auswirkungen der Diversifizierung zu verstehen.
Szenario: Diversifizierung bei Inferenz-Workloads in Echtzeit
Für eine Online-Inferenz-Arbeitslast in Echtzeit auf Spot-Instances können Sie einen Karpenter konfigurieren, um die Verteilung zwischen kompatiblen GPU-Instance-Familien und Generationen NodePool zu diversifizieren. Dieser Ansatz gewährleistet eine hohe Verfügbarkeit, indem er aus mehreren Spot-Pools schöpft und gleichzeitig die Leistung aufgrund von Einschränkungen der GPU-Funktionen, des Speichers und der Architektur aufrechterhalten wird. Er unterstützt die Verwendung von Alternativen, wenn die Instance-Kapazität begrenzt ist, wodurch Unterbrechungen minimiert und die Inferenzlatenz optimiert wird. Dieses Beispiel NodePool besagt, dass Sie Instanzen der Serien G und P verwenden sollten, die größer als 3 sind und über mehr als 20 GB GPU-Speicher verfügen.
Beispiel
apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: gpu-inference-spot spec: template: metadata: labels: role: gpu-spot-worker spec: requirements: - key: karpenter.sh/capacity-type operator: In values: ["spot"] # Use Spot Instances - key: karpenter.k8s.aws/instance-category operator: In values: ["g", "p"] # Diversifies across G-series and P-series - key: karpenter.k8s.aws/instance-generation operator: Gt values: ["3"] # Selects instance generations greater than 3 - key: kubernetes.io/arch operator: In values: ["amd64"] # Specifies AMD64 architecture, compatible with NVIDIA GPUs - key: karpenter.k8s.aws/instance-gpu-memory operator: Gt values: ["20480"] # Ensures more than 20GB (20480 MiB) total GPU memory taints: - key: nvidia.com/gpu effect: NoSchedule nodeClassRef: name: gpu-inference-ec2 group: karpenter.k8s.aws kind: EC2NodeClass expireAfter: 720h limits: cpu: 100 memory: 100Gi disruption: consolidationPolicy: WhenEmptyOrUnderutilized consolidateAfter: 5m # Enables consolidation of underutilized nodes after 5 minutes
Implementieren Sie Checkpointing für Trainingsjobs mit langer Laufzeit
Checkpointing ist eine Technik zur Fehlertoleranz, bei der der Status eines Prozesses in regelmäßigen Abständen gespeichert wird, sodass er im Falle von Unterbrechungen am zuletzt gespeicherten Punkt fortgesetzt werden kann. Beim maschinellen Lernen wird es häufig mit Training in Verbindung gebracht. Bei Jobs mit langer Laufzeit können Modellgewichte und Optimizer-Status eingespart werden, sodass das Training nach Ausfällen wie Hardwareproblemen oder Spot-Instance-Unterbrechungen wieder aufgenommen werden kann.
Sie verwenden Checkpoints, um den Status von Modellen für maschinelles Lernen (ML) während des Trainings zu speichern. Checkpoints sind Schnappschüsse des Modells und können mit den Callback-Funktionen von ML-Frameworks konfiguriert werden. Sie können die gespeicherten Checkpoints verwenden, um einen Trainingsjob vom zuletzt gespeicherten Checkpoint aus neu zu starten. Mithilfe von Checkpoints speichern Sie Ihre Modell-Snapshots während des Trainings aufgrund einer unerwarteten Unterbrechung des Trainingsauftrags oder der Trainingsinstanz. Auf diese Weise können Sie das Training des Modells in Zukunft von einem Checkpoint aus fortsetzen. Zusätzlich zur Implementierung eines Node-Resilienzsystems empfehlen wir die Implementierung von Checkpointing, um die Auswirkungen von Unterbrechungen, einschließlich solcher, die durch Hardwareausfälle oder Unterbrechungen der Amazon EC2 Spot-Instance verursacht werden, zu minimieren.
Ohne Checkpointing können Unterbrechungen zu vergeudeter Rechenzeit und Fortschrittsverlusten führen, was bei lang andauernden Trainingsaufträgen kostspielig ist. Durch Checkpointing können Jobs ihren Status regelmäßig speichern (z. B. Modellgewichte und Optimiererstatus) und nach einer Unterbrechung am letzten Checkpoint (zuletzt verarbeiteter Batch) fortgesetzt werden. Um Checkpointing zu implementieren, entwerfen Sie Ihre Anwendung so, dass sie Daten in großen Batches verarbeitet und Zwischenergebnisse während des Trainingsauftrags über den Mountpoint for Amazon S3 CSI Driver in einem persistenten Speicher, z. B. in einem Amazon S3-Bucket, speichert.
Anwendungsfälle
Checkpointing ist besonders in bestimmten Szenarien von Vorteil, um ein Gleichgewicht zwischen Fehlertoleranz und Leistungsaufwand herzustellen. Erwägen Sie den Einsatz von Checkpointing in den folgenden Fällen:
-
Die Auftragsdauer überschreitet einige Stunden: Für lange Trainingsjobs (z. B. >1—2 Stunden für kleine Modelle oder days/weeks für große Basismodelle mit Milliarden von Parametern), bei denen der Verlust des Fortschritts aufgrund von Unterbrechungen kostspielig ist. Kürzere Aufträge rechtfertigen den Aufwand möglicherweise nicht. I/O
-
Für Spot-Instances oder Hardwareausfälle: In Umgebungen, die anfällig für Unterbrechungen sind, wie EC2 Spot (2 Minuten im Voraus) oder Hardwarefehlern (z. B. GPU-Speicherfehler), ermöglicht Checkpointing eine schnelle Wiederaufnahme, sodass Spot für Kosteneinsparungen bei fehlertoleranten Workloads rentabel ist.
-
Verteiltes Training in großem Maßstab: Für Setups mit hundreds/thousands mehreren Beschleunigern (z. B. >100 GPUs), bei denen die mittlere Zeit zwischen Ausfällen linear mit der Skalierung abnimmt. Wird für model/data Parallelität verwendet, um den gleichzeitigen Checkpoint-Zugriff zu verarbeiten und komplette Neustarts zu vermeiden.
-
Large-scale Modelle mit hohem Ressourcenbedarf: Bei LLM-Trainings im Petabyte-Bereich, bei denen Ausfälle aufgrund der Clustergröße unvermeidlich sind, optimieren abgestufte Ansätze (schnelle lokale Abläufe alle 5-30 Minuten bei vorübergehenden Störungen, dauerhaft stündlich bei größeren Ausfällen) die Wiederherstellungszeit im Vergleich zur Effizienz.
Verwenden Sie ML Capacity Blocks zur Sicherung der Kapazität von P- und Trainium-Instances
Capacity Blocks for ML ermöglichen es Ihnen, sehr gefragte GPU-Instances zu reservieren, insbesondere P-Instances (z. B. p6-b200, p5, p5e, p5en, p4d, p4de) und Trainium-Instances (z. B. trn1, trn2), um entweder fast sofort oder zu einem späteren Zeitpunkt zu starten, um Ihre kurzfristigen Machine Learning-Workloads (ML) zu unterstützen. Diese Reservierungen sind ideal, um die Kapazität für rechenintensive Aufgaben wie Modelltraining und Feinabstimmung sicherzustellen. Die Preise für EC2 Capacity Blocks setzen sich aus einer Reservierungsgebühr und einer Betriebssystemgebühr zusammen. Weitere Informationen zur Preisgestaltung finden Sie unter Preise für EC2-Kapazitätsblöcke für ML.
Um GPUs für AI/ML Workloads auf Amazon EKS zu reservieren, um eine vorhersehbare Kapazitätsabsicherung zu gewährleisten, empfehlen wir, ML-Kapazitätsblöcke für kurzfristige oder Kapazitätsreservierungen (ODCRs) für On-Demand allgemeine Kapazitätsabsicherungen zu nutzen.
-
ODCRs ermöglichen es Ihnen, EC2-Instance-Kapazität (z. B. GPU-Instances wie g5 oder p5) in einer bestimmten Availability Zone für einen bestimmten Zeitraum zu reservieren, um die Verfügbarkeit auch bei hoher Nachfrage sicherzustellen. ODCRs sind nicht langfristig gebunden, aber Sie zahlen den On-Demand Tarif für die reservierte Kapazität, unabhängig davon, ob sie genutzt oder inaktiv ist. In EKS werden ODCRs von Knotentypen wie https://karpenter.sh/
Karpenter und verwalteten Knotengruppen unterstützt. https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html Um ODCRs in Karpenter zu priorisieren, konfigurieren Sie das so, dass das Feld verwendet wird. NodeClass capacityReservationSelectorTermsWeitere Informationen finden Sie in der Karpenter-Dokumentation. NodePools -
Kapazitätsblöcke sind ein spezieller Reservierungsmechanismus für GPU- (z. B. p5, p4d) oder Trainium- (trn1, trn2) -Instances, der für kurzfristige ML-Workloads wie Modelltraining, Feinabstimmung oder Experimente konzipiert ist. Sie reservieren Kapazität für einen bestimmten Zeitraum (in der Regel 24 Stunden bis 182 Tage), der an einem zukünftigen Datum beginnt, und zahlen nur für die reservierte Zeit. Sie sind im Voraus bezahlt, erfordern eine vorherige Planung des Kapazitätsbedarfs und unterstützen keine automatische Skalierung. Sie werden jedoch in EC2 gespeichert, um Netzwerke mit niedriger Latenz zu ermöglichen. UltraClusters Sie berechnen nur für den reservierten Zeitraum. Weitere Informationen finden Sie unter Suchen und Kaufen von Kapazitätsblöcken. Oder richten Sie zunächst verwaltete Knotengruppen mit Kapazitätsblöcken ein. Folgen Sie dazu den Anweisungen unter Erstellen einer verwalteten Knotengruppe mit Kapazitätsblöcken für ML.
Reservieren Sie Kapazität über die AWS-Managementkonsole und konfigurieren Sie Ihre Knoten für die Verwendung von ML-Kapazitätsblöcken. Planen Sie Reservierungen auf der Grundlage von Workload-Zeitplänen und testen Sie in einem Staging-Cluster. Weitere Informationen finden Sie in der Dokumentation zu Capacity Blocks.
On-DemandErwägen Sie Amazon EC2 Spot oder On-Demand Capacity Reservations (ODCRs) für G Amazon EC2-Instances
Für G Amazon EC2-Instances sollten Sie die verschiedenen Kaufoptionen von Amazon EC2 Spot-Instances On-Demand und Kapazitätsreservierungen in Betracht ziehen. On-Demand ODCRs ermöglichen es Ihnen, EC2-Instance-Kapazitäten in einer bestimmten Availability Zone für eine bestimmte Dauer zu reservieren, sodass die Verfügbarkeit auch bei hoher Nachfrage gewährleistet ist. Im Gegensatz zu ML Capacity Blocks, die nur für P- und Trainium-Instances verfügbar sind, können ODCRs für eine breitere Palette von Instance-Typen verwendet werden, einschließlich G-Instances. Dadurch eignen sie sich für Workloads, die unterschiedliche GPU-Funktionen wie Inferenz oder Grafik erfordern. Wenn Sie Amazon EC2 Spot-Instances verwenden, ist die Möglichkeit, zwischen verschiedenen Instance-Typen, Größen und Verfügbarkeitszonen zu variieren, entscheidend, um länger auf Spot bleiben zu können.
ODCRs haben keine langfristige Bindung, aber Sie zahlen den On-Demand Tarif für die reservierte Kapazität, unabhängig davon, ob sie genutzt oder inaktiv ist. ODCRs können für den sofortigen Einsatz erstellt oder für einen späteren Zeitpunkt geplant werden, was Flexibilität bei der Kapazitätsplanung bietet. In Amazon EKS werden ODCRs von Knotentypen wie https://karpenter.sh/capacityReservationSelectorTerms Weitere Informationen finden Sie in der Karpenter-Dokumentation. NodePools
Ziehen Sie andere beschleunigte Instance-Typen und -Größen in Betracht
Die Auswahl der geeigneten beschleunigten Instance und Größe ist unerlässlich, um sowohl die Leistung als auch die Kosten Ihrer ML-Workloads auf Amazon EKS zu optimieren. Beispielsweise haben verschiedene GPU-Instance-Familien unterschiedliche Leistungen und Funktionen, wie z. B. GPU-Speicher. Um Ihnen bei der Auswahl der Option mit dem besten Preis-Leistungs-Verhältnis zu helfen, überprüfen Sie die verfügbaren GPU-Instances auf der Seite
Wenn Sie eine GPU-Instanz in einem EKS-Knoten verwenden, befindet sich der nvidia-device-plugin-daemonset Pod standardmäßig im kube-system Namespace. Um einen schnellen Überblick darüber zu bekommen, ob Sie die GPU (s) in Ihrer Instance voll ausnutzen, können Sie https://docs.nvidia.com/deploy/nvidia-smi/index.html
kubectl exec nvidia-device-plugin-daemonset-xxxxx \ -n kube-system -- nvidia-smi \ --query-gpu=index,power.draw,power.limit,temperature.gpu,utilization.gpu,utilization.memory,memory.free,memory.used \ --format=csv -l 5
-
Wenn der
utilization.memoryWert nahe bei 100% liegt, sind Ihre Codes wahrscheinlich speichergebunden. Dies bedeutet, dass die GPU (Speicher) voll ausgelastet ist, könnte aber darauf hindeuten, dass weitere Leistungsoptimierungen untersucht werden sollten. -
Wenn der nahe bei 100%
utilization.gpuliegt, bedeutet das nicht unbedingt, dass die GPU voll ausgelastet ist. Eine bessere Kennzahl ist das Verhältnis vonpower.drawzupower.limit. Wenn dieses Verhältnis 100% oder mehr beträgt, nutzen Ihre Codes die Rechenkapazität der GPU voll aus. -
Die
-l 5Flagge besagt, dass die Metriken alle 5 Sekunden ausgegeben werden sollen. Bei einem einzelnen GPU-Instanztyp wird das Indexabfrage-Flag nicht benötigt.
Weitere Informationen finden Sie unter GPU-Instances in der AWS-Dokumentation.
Optimieren Sie die GPU-Ressourcenzuweisung mit Time-Slicing MIG und fraktionierter GPU-Zuweisung
Statische Ressourcenbeschränkungen in Kubernetes (z. B. CPU, Arbeitsspeicher, GPU-Anzahl) können zu einer Über- oder Unterauslastung führen, insbesondere bei dynamischen Workloads wie Inferenz. AI/ML Die Auswahl der richtigen GPU ist wichtig. Bei Workloads mit geringem Volumen oder hoher Auslastung ermöglicht Time-Slicing, dass sich mehrere Workloads eine einzige GPU teilen, indem sie ihre Rechenressourcen gemeinsam nutzen, was potenziell die Effizienz verbessert und die Verschwendung reduziert. Die gemeinsame Nutzung der GPU kann durch verschiedene Optionen erreicht werden:
-
Nutzen Sie die Knotenauswahl und die Knotenaffinität, um die Planung zu beeinflussen: Stellen Sie sicher, dass die bereitgestellten Knoten und Pods auf den für die jeweilige Arbeitslast geeigneten GPUs geplant sind (z. B.)
karpenter.k8s.aws/instance-gpu-name: "a100" -
Time-Slicing: Plant Workloads so, dass sie sich im Laufe der Zeit die Rechenressourcen einer GPU teilen, sodass eine gleichzeitige Ausführung ohne physische Partitionierung möglich ist. Dies ist ideal für Workloads mit variablen Rechenanforderungen, denen es jedoch möglicherweise an Speicherisolierung mangelt.
-
Multi-Instance GPU (MIG): MIG ermöglicht die Partitionierung einer einzelnen NVIDIA-GPU in mehrere, isolierte Instanzen und wird von den GPUs NVIDIA Ampere (z. B. A100 GPU), NVIDIA Hopper (z. B. H100 GPU) und NVIDIA Blackwell (z. B. Blackwell GPUs) unterstützt. Jede MIG-Instance erhält dedizierte Rechen- und Speicherressourcen, was die gemeinsame Nutzung von Ressourcen in Umgebungen mit mehreren Mandanten oder Workloads, die Ressourcengarantien erfordern, ermöglicht. So können Sie die GPU-Ressourcenauslastung optimieren, einschließlich Szenarien wie der Bereitstellung mehrerer Modelle mit unterschiedlichen Batchgrößen durch Time-Slicing.
-
Fraktionierte GPU-Zuweisung: Verwendet softwarebasierte Planung, um Teile der Rechenleistung oder des Speichers einer GPU Workloads zuzuweisen und bietet so Flexibilität für dynamische Workloads. Der NVIDIA KAI Scheduler
, Teil der Run:ai Plattform, ermöglicht dies, indem er es Pods ermöglicht, Bruchteile von GPU-Ressourcen anzufordern.
Um diese Funktionen in EKS zu aktivieren, können Sie das NVIDIA Device Plugin bereitstellen, das GPUs als planbare Ressourcen bereitstellt und Timeslicing und MIG unterstützt. Weitere Informationen finden Sie unter Time-Slicing GPUs in Kubernetes
Beispiel
Um beispielsweise Time-Slicing mit dem NVIDIA Device Plugin zu aktivieren:
apiVersion: v1 kind: ConfigMap metadata: name: nvidia-device-plugin-config namespace: kube-system data: config.yaml: | version: v1 sharing: timeSlicing: resources: - name: nvidia.com/gpu replicas: 4 # Allow 4 pods to share each GPU
Beispiel
Um beispielsweise den KAI Scheduler für die fraktionierte GPU-Zuweisung zu verwenden, stellen Sie ihn zusammen mit dem NVIDIA GPU Operator bereit und geben Sie fraktionierte GPU-Ressourcen in der Pod-Spezifikation an:
apiVersion: v1 kind: Pod metadata: name: fractional-gpu-pod-example annotations: gpu-fraction: "0.5" # Annotation for 50% GPU labels: runai/queue: "default" # Required queue assignment spec: containers: - name: ml-workload image: nvcr.io/nvidia/pytorch:25.04-py3 resources: limits: nvidia.com/gpu: 1 nodeSelector: nvidia.com/gpu: "true" schedulerName: kai-scheduler
Ausfallsicherheit der Knoten und Verwaltung von Trainingsaufträgen
Implementieren Sie Node-Integritätsprüfungen mit automatisierter Wiederherstellung
Bei verteilten Trainingsjobs auf Amazon EKS, die eine häufige Kommunikation zwischen den Knoten erfordern, wie z. B. das Training mehrerer GPU-Modelle über mehrere Knoten hinweg, können Hardwareprobleme wie GPU- oder EFA-Ausfälle zu Unterbrechungen der Trainingsjobs führen. Diese Unterbrechungen können zum Verlust des Trainingsfortschritts und zu erhöhten Kosten führen, insbesondere bei AI/ML Workloads mit langer Laufzeit, die auf stabiler Hardware angewiesen sind.
Um die Widerstandsfähigkeit gegen Hardwareausfälle wie GPU-Ausfälle in EKS-Clustern, auf denen GPU-Workloads ausgeführt werden, zu erhöhen, empfehlen wir, entweder den EKS Node Monitoring Agent mit Auto Repair oder Amazon zu nutzen. SageMaker HyperPod Der EKS Node Monitoring Agent mit Auto Repair bietet zwar Funktionen wie die Überwachung des Knotenzustands und die automatische Reparatur mithilfe von Kubernetes-Standardmechanismen, SageMaker HyperPod bietet aber auch gezielte Ausfallsicherheit und zusätzliche Funktionen, die speziell für groß angelegte ML-Schulungen entwickelt wurden, wie z. B. gründliche Zustandsprüfungen und automatische Wiederaufnahme der Arbeit.
-
Der EKS Node Monitoring Agent mit Node Auto Repair überwacht kontinuierlich den Zustand der Knoten, indem er Protokolle liest und anwendet. Dazu gehören auch Standardbedingungen wie
ReadyBedingungen NodeConditions, die für beschleunigte Hardware spezifisch sind, um Probleme wie GPU- oder Netzwerkfehler zu erkennen. Wenn ein Knoten als fehlerhaft eingestuft wird, sperrt Node Auto Repair ihn ab und ersetzt ihn durch einen neuen Knoten. Die Neuplanung von Pods und der Neustart von Jobs basieren auf den Standard-Kubernetes-Mechanismen und der Neustartrichtlinie des Jobs. -
Der Agent für SageMaker HyperPod
gründliche Integritätsprüfungen und Statusüberwachung überwacht kontinuierlich den Zustand der GPU und der Instances. Trainium-based Er ist auf AI/ML Workloads zugeschnitten und verwendet Labels (z. B. Node-Health-Status), um den Zustand der Knoten zu verwalten. Wenn ein Knoten als fehlerhaft eingestuft wird, wird der automatische Austausch der fehlerhaften Hardware, wie GPUs, HyperPod ausgelöst. Es erkennt standardmäßig netzwerkbedingte Ausfälle für EFA anhand seiner grundlegenden Integritätsprüfungen und unterstützt die automatische Wiederaufnahme bei unterbrochenen Trainingsjobs, sodass Jobs vom letzten Checkpoint aus fortgesetzt werden können, wodurch Unterbrechungen bei umfangreichen ML-Aufgaben minimiert werden.
Stellen Sie sowohl für EKS Node Monitoring Agent mit Auto Repair als auch für SageMaker HyperPod Cluster, die EFA verwenden, sicher, dass der AWS-EFA-Treiber installiert ist, um EFA-specific Messwerte wie RDMA-Fehler (Remote Direct Memory Access) und Paketverluste zu überwachen. https://docs.aws.amazon.com/eks/latest/userguide/node-efa.html Darüber hinaus empfehlen wir, CloudWatch Observability bereitzustellen Add-on oder Tools wie DCGM Exporter mit Prometheus und Grafana zu verwenden, um EFA, GPU und, falls, bestimmte Metriken im Zusammenhang mit ihren Funktionen zu überwachen. SageMaker HyperPod
Deaktivieren Sie Karpenter Consolidation für unterbrechungssensitive Workloads
Für Workloads, die empfindlich auf Unterbrechungen reagieren, z. B. bei der Verarbeitung, umfangreichen AI/ML Prognoseaufgaben oder Schulungen, empfehlen wir, die Konsolidierungsrichtlinien von
Die WhenEmptyOrUnderutilized Konsolidierungspolitik kann Knoten vorzeitig beenden, was zu längeren Ausführungszeiten führt. Beispielsweise können Unterbrechungen die Wiederaufnahme des Jobs verzögern, da die Pods neu geplant werden oder Daten neu geladen werden, was bei Batch-Inferenz-Jobs mit langer Laufzeit kostspielig sein kann. Um dem entgegenzuwirken, können Sie den Wert consolidationPolicy auf festlegen WhenEmpty und eine consolidateAfter Dauer (z. B. 1 Stunde) konfigurieren, sodass Knoten auch bei Arbeitslastspitzen erhalten bleiben. Beispiel:
disruption: consolidationPolicy: WhenEmpty consolidateAfter: 60m
Dieser Ansatz verbessert die Pod-Startlatenz für hohe Batch-Inferenz-Workloads und andere unterbrechungssensitive Aufgaben, wie z. B. Online-Inferenzdatenverarbeitung in Echtzeit oder Modelltraining, bei denen die Kosten einer Unterbrechung die Einsparungen bei den Rechenkosten überwiegen. Karpenter Disruption Budgets ist eine weitere Funktion zur Verwaltung von Störungen in Karpenter NodePool .
Verwenden Sie ttl, um Kubernetes-Jobs SecondsAfterFinished zu automatisieren Clean-Up
Wir empfehlen, die Einstellung ttlSecondsAfterFinished für Kubernetes-Jobs in Amazon EKS so einzustellen, dass abgeschlossene Auftragsobjekte automatisch gelöscht werden. Verbleibende Auftragsobjekte verbrauchen Cluster-Ressourcen wie API-Serverspeicher und erschweren die Überwachung, da die Dashboards überladen sind (z. B. Grafana, Amazon). CloudWatch Wenn Sie beispielsweise eine TTL von 1 Stunde festlegen, wird sichergestellt, dass Jobs kurz nach Abschluss entfernt werden, sodass Ihr Cluster stets sauber bleibt. Weitere Informationen finden Sie unter Automatische Bereinigung für abgeschlossene Jobs.
Konfigurieren Sie Low-Priority Job Preemption für Higher-Priority Jobs/workloads
Für AI/ML Workloads mit gemischter Priorität in Amazon EKS können Sie die Auftragsprävention mit niedriger Priorität konfigurieren, um sicherzustellen, dass Aufgaben mit höherer Priorität (z. B. Echtzeit-Inferenz) umgehend Ressourcen erhalten. Ohne Präemption können Workloads mit niedriger Priorität wie Batch-Prozesse (z. B. Batch-Inferenz, Datenverarbeitung), Nicht-Batch-Dienste (z. B. Hintergrundaufgaben, Cron-Jobs) oder Jobs (z. B. Webservices) kritische Pods verzögern, indem sie Knoten belegen. CPU/memory-intensive Mithilfe der Präemption kann Kubernetes Pods mit niedriger Priorität entfernen, wenn Pods mit hoher Priorität Ressourcen benötigen. Dadurch wird eine effiziente Ressourcenzuweisung auf Knoten mit GPUs, CPUs oder Arbeitsspeicher gewährleistet. Wir empfehlen, Kubernetes zu verwenden, um Prioritäten zuzuweisen und das Räumungsverhalten zu kontrollieren. PriorityClass PodDisruptionBudget
apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: low-priority value: 100 --- spec: priorityClassName: low-priority
Weitere Informationen finden Sie in der Kubernetes-Dokumentation zu Priority and Preemption.
Skalierung und Leistung von Anwendungen
Passen Sie die Rechenkapazität für ML-Workloads mit Karpenter oder Static Nodes an
Um eine kosteneffiziente und reaktionsschnelle Rechenkapazität für Machine-Learning-Workflows (ML) auf Amazon EKS sicherzustellen, empfehlen wir, Ihre Node-Provisioning-Strategie an die Merkmale und Kostenverpflichtungen Ihrer Workloads anzupassen. Im Folgenden finden Sie zwei Ansätze, die Sie in Betracht ziehen sollten: Just-in-Time-Skalierung mit Karpenter
-
Just-in-time Skalierer für Datenebenen wie Karpenter: Für dynamische ML-Workflows mit variablen Rechenanforderungen (z. B. GPU-based Inferenz und anschließendes CPU-based Plotten) empfehlen wir die Verwendung von Just-in-Time-Datenebenen-Skalierern wie Karpenter.
-
Verwenden Sie statische Knotengruppen für vorhersehbare Workloads: Für vorhersehbare, stationäre ML-Workloads oder bei Verwendung von Reserved Instances können von EKS verwaltete Knotengruppen dazu beitragen, dass reservierte Kapazität vollständig bereitgestellt und genutzt wird, wodurch Einsparungen maximiert werden. Dieser Ansatz ist ideal für bestimmte Instance-Typen, die über RIs oder ODCRs übertragen werden.
Beispiel
Dies ist ein Beispiel für ein vielseitiges Karpenter NodePoolg Amazon EC2-Instances ermöglicht, bei denen mehr als drei Instanzen generiert werden.
apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: gpu-inference spec: template: spec: nodeClassRef: group: karpenter.k8s.aws kind: EC2NodeClass name: default requirements: - key: karpenter.sh/capacity-type operator: In values: ["on-demand"] - key: karpenter.k8s.aws/instance-category operator: In values: ["g"] - key: karpenter.k8s.aws/instance-generation operator: Gt values: ["3"] - key: kubernetes.io/arch operator: In values: ["amd64"] taints: - key: nvidia.com/gpu effect: NoSchedule limits: cpu: "1000" memory: "4000Gi" nvidia.com/gpu: "10" *# Limit the total number of GPUs to 10 for the NodePool* disruption: consolidationPolicy: WhenEmpty consolidateAfter: 60m expireAfter: 720h
Beispiel
Beispiel für die Verwendung statischer Knotengruppen für eine Trainingslast:
apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: ml-cluster region: us-west-2 managedNodeGroups: - name: gpu-node-group instanceType: p4d.24xlarge minSize: 2 maxSize: 2 desiredCapacity: 2 taints: - key: nvidia.com/gpu effect: NoSchedule
Verwenden Sie Einschränkungen und Toleranzen, um zu verhindern, dass nicht beschleunigte Workloads auf beschleunigten Instances geplant werden
Die Planung nicht beschleunigter Workloads auf GPU-Ressourcen ist nicht recheneffizient. Wir empfehlen die Verwendung von Taints und Tolerance, um sicherzustellen, dass Pods für nicht beschleunigte Workloads nicht auf ungeeigneten Knoten geplant werden. Weitere Informationen finden Sie in der Kubernetes-Dokumentation.
Skalieren Sie basierend auf der Modellleistung
Für Inferenz-Workloads empfehlen wir die Verwendung von Kubernetes Event-Driven Autoscaling (KEDA) zur Skalierung auf der Grundlage von Modellleistungskennzahlen wie Inferenzanforderungen oder Token-Durchsatz mit angemessenen Abklingzeiten. Statische Skalierungsrichtlinien können zu viel oder zu wenig Ressourcen bereitstellen, was sich auf Kosten und Latenz auswirkt. Erfahren Sie mehr in der KEDA-Dokumentation.
Dynamische Ressourcenzuweisung für erweitertes GPU-Management
Die dynamische Ressourcenzuweisung (DRA)
-
Fine-grained GPU-Zuweisung
-
Erweiterte Sharing-Mechanismen wie Multi-Process Service (MPS) und Multi-Instance GPU (MIG)
-
Unterstützung für Hardwarearchitekturen der nächsten Generation, einschließlich NVIDIA GB200 UltraServers
Bei der herkömmlichen GPU-Zuweisung werden GPUs als undurchsichtige Ganzzahlressourcen behandelt, was zu einer erheblichen Unterauslastung führt (in Produktionsclustern häufig 30-40%). Dies liegt daran, dass Workloads exklusiven Zugriff auf ganze GPUs erhalten, auch wenn nur ein Bruchteil der Ressourcen benötigt wird. DRA transformiert dieses Modell, indem es eine strukturierte, deklarative Zuweisung einführt, die dem Kubernetes-Scheduler einen vollständigen Überblick über Hardwaremerkmale und Workload-Anforderungen bietet. Dies ermöglicht intelligente Platzierungsentscheidungen und eine effiziente gemeinsame Nutzung von Ressourcen.
Vorteile der Verwendung von DRA anstelle des NVIDIA-Geräte-Plug-ins
Das NVIDIA-Geräte-Plugin (ab Version0.12.0) unterstützt GPU-Sharing-Mechanismen wie Time-Slicing, MPS und MIG. Es gibt jedoch architektonische Einschränkungen, die DRA behebt.
Einschränkungen beim NVIDIA-Geräte-Plug-In
-
Statische Konfiguration: Konfigurationen zur gemeinsamen Nutzung von GPUs (Time-Slicing-Replikate und MPS-Einstellungen) erfordern eine clusterweite Vorkonfiguration.
ConfigMapsDies macht es schwierig, unterschiedliche Strategien zur gemeinsamen Nutzung für unterschiedliche Workloads bereitzustellen. -
Eingeschränkte granulare Auswahl: Während das Geräte-Plug-In GPU-Eigenschaften über Node-Labels verfügbar macht, können Workloads bestimmte GPU-Konfigurationen (Speichergröße und Rechenkapazitäten) nicht dynamisch als Teil der Planungsentscheidung anfordern.
-
Keine knotenübergreifende Ressourcenkoordination: Es ist nicht möglich, verteilte GPU-Ressourcen über mehrere Knoten zu verwalten oder komplexe Topologieanforderungen wie NVLink-Domänen für Systeme wie NVIDIA GB200 zu formulieren.
-
Scheduler-Einschränkungen: Der Kubernetes-Scheduler behandelt GPU-Ressourcen als undurchsichtige Ganzzahlen, was seine Fähigkeit einschränkt, topologiebewusste Entscheidungen zu treffen oder komplexe Ressourcenabhängigkeiten zu bewältigen.
-
Komplexität der Konfiguration: Die Einrichtung verschiedener Strategien zur gemeinsamen Nutzung erfordert mehrere
ConfigMapsund sorgfältige Knotenkennzeichnungen, was zu betrieblicher Komplexität führt.
Lösungen mit DRA
-
Dynamische Ressourcenauswahl: Mit DRA können Workloads bei der Anforderung detaillierte Anforderungen (GPU-Speicher, Treiberversionen und spezifische Attribute) angeben.
resourceclaimsDies ermöglicht einen flexibleren Ressourcenabgleich. -
Topologiebewusstsein: Mithilfe strukturierter Parameter und Geräteselektoren bewältigt DRA komplexe Anforderungen wie knotenübergreifende GPU-Kommunikation und speicherkohärente Verbindungen.
-
Cross-node Ressourcenmanagement:
computeDomainsermöglicht die Koordination verteilter GPU-Ressourcen über mehrere Knoten hinweg, was für Systeme wie GB200 mit IMEX-Kanälen von entscheidender Bedeutung ist. -
Workload-specific Konfiguration: Jede Konfiguration
ResourceClaimspezifiziert unterschiedliche Strategien und Konfigurationen für die gemeinsame Nutzung und ermöglicht so eine feinkörnige Steuerung pro Workload statt clusterweiter Einstellungen. -
Verbesserte Scheduler-Integration: DRA stellt dem Scheduler detaillierte Geräteinformationen zur Verfügung und ermöglicht intelligentere Platzierungsentscheidungen auf der Grundlage der Hardwaretopologie und der Ressourceneigenschaften.
Wichtig: DRA ersetzt das NVIDIA-Geräte-Plug-In nicht vollständig. Der NVIDIA DRA-Treiber arbeitet zusammen mit dem Geräte-Plug-In, um erweiterte Funktionen bereitzustellen. Das Geräte-Plug-In übernimmt weiterhin die grundlegende GPU-Erkennung und -Verwaltung, während DRA erweiterte Zuweisungs- und Planungsfunktionen bietet.
Von DRA unterstützte Instanzen und ihre Funktionen
Die DRA-Unterstützung variiert je nach Amazon EC2-Instance-Familie und GPU-Architektur, wie in der folgenden Tabelle dargestellt.
| Instance-Familie | GPU-Typ | Time-slicing | MIG-Unterstützung | MPS-Unterstützung | IMEX-Unterstützung | Anwendungsfälle |
|---|---|---|---|---|---|---|
|
G5 |
NVIDIA A10G |
Ja |
Nein |
Ja |
Nein |
Inferenz- und Grafik-Workloads |
|
G6 |
NVIDIA L4 |
Ja |
Nein |
Ja |
Nein |
KI-Inferenz und Videoverarbeitung |
|
G6e |
NVIDIA L40S |
Ja |
Nein |
Ja |
Nein |
Training, Inferenz und Grafik |
|
P4d/P4de |
NVIDIA A100 |
Ja |
Ja |
Ja |
Nein |
Large-scale Schulung und HPC |
|
P5 |
NVIDIA H100 |
Ja |
Ja |
Ja |
Nein |
Schulung zum Grundmodell |
|
P6 |
NVIDIA B200 |
Ja |
Ja |
Ja |
Nein |
Modelle mit Milliarden oder Billionen Parametern, verteiltes Training und Inferenz |
|
P6e |
NVIDIA GB200 |
Ja |
Ja |
Ja |
Ja |
Modelle mit Milliarden oder Billionen Parametern, verteiltes Training und Inferenz |
Im Folgenden werden die einzelnen Funktionen in der Tabelle beschrieben:
-
Time-slicing: Ermöglicht es mehreren Workloads, GPU-Rechenressourcen im Laufe der Zeit gemeinsam zu nutzen.
-
Multi-Instance GPU (MIG): Hardware-level Partitionierung, die isolierte GPU-Instanzen erzeugt.
-
Multi-Process service (MPS): Ermöglicht die gleichzeitige Ausführung mehrerer CUDA-Prozesse auf einer einzelnen GPU.
-
Internode Memory Exchange (IMEX): Memory-coherent Kommunikation zwischen Knoten für GB200. UltraServers
Weitere Ressourcen
Weitere Informationen zu Kubernetes-DRA- und NVIDIA-DRA-Treibern finden Sie in den folgenden Ressourcen unter: GitHub
-
Dynamische Ressourcenzuweisung in Kubernetes https://github.com/kubernetes/dynamic-resource-allocation
Richten Sie eine dynamische Ressourcenzuweisung für eine erweiterte GPU-Verwaltung ein
Das folgende Thema zeigt Ihnen, wie Sie die dynamische Ressourcenzuweisung (DRA) für die erweiterte GPU-Verwaltung einrichten.
Voraussetzungen
Stellen Sie vor der Implementierung von DRA auf Amazon EKS sicher, dass Ihre Umgebung die folgenden Anforderungen erfüllt.
Cluster-Konfiguration
-
Amazon EKS-Cluster mit ausgeführter Version
1.33oder höher -
Von Amazon EKS verwaltete Knotengruppen (DRA wird derzeit nur von verwalteten Knotengruppen mit AL2023- und Bottlerocket NVIDIA-optimierten AMIs unterstützt, nicht von Karpenter)
-
NVIDIA-Worker-Knoten GPU-enabled mit den entsprechenden Instance-Typen
Erforderliche Komponenten
-
Version des NVIDIA-Geräte-Plugins
0.17.1oder höher -
NVIDIA DRA-Treiberversion
25.3.0oder höher
Schritt 1: Erstellen Sie einen Cluster mit einer DRA-enabled Knotengruppe mithilfe von eksctl
-
Erstellen Sie eine Cluster-Konfigurationsdatei mit dem Namen:
dra-eks-cluster.yaml--- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: dra-eks-cluster region: us-west-2 version: '1.33' managedNodeGroups: - name: gpu-dra-nodes amiFamily: AmazonLinux2023 instanceType: g6.12xlarge desiredCapacity: 2 minSize: 1 maxSize: 3 labels: node-type: "gpu-dra" nvidia.com/gpu.present: "true" taints: - key: nvidia.com/gpu value: "true" effect: NoSchedule -
Erstellen Sie den Cluster:
eksctl create cluster -f dra-eks-cluster.yaml
Schritt 2: Stellen Sie das NVIDIA-Geräte-Plugin bereit
Stellen Sie das NVIDIA-Geräte-Plugin bereit, um die grundlegende GPU-Erkennung zu ermöglichen:
-
Fügen Sie das Helm-Repository für das NVIDIA-Geräte-Plugin hinzu:
helm repo add nvidia https://nvidia.github.io/k8s-device-plugin helm repo update -
Erstellen Sie benutzerdefinierte Werte für das Geräte-Plugin:
cat <<EOF > nvidia-device-plugin-values.yaml gfd: enabled: true nfd: enabled: true tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule EOF -
Installieren Sie das NVIDIA-Geräte-Plug-In:
helm install nvidia-device-plugin nvidia/nvidia-device-plugin \ --namespace nvidia-device-plugin \ --create-namespace \ --version 0.17.1 \ --values nvidia-device-plugin-values.yaml
Schritt 3: Stellen Sie den NVIDIA DRA-Treiber Helm Chart bereit
-
Erstellen Sie eine
dra-driver-values.yamlWertedatei für den DRA-Treiber:--- nvidiaDriverRoot: / gpuResourcesEnabledOverride: true resources: gpus: enabled: true computeDomains: enabled: true # Enable for GB200 IMEX support controller: tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule kubeletPlugin: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: "nvidia.com/gpu.present" operator: In values: ["true"] tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule -
Fügen Sie das NVIDIA NGC Helm-Repository hinzu:
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia helm repo update -
Installieren Sie den NVIDIA DRA-Treiber:
helm install nvidia-dra-driver nvidia/nvidia-dra-driver-gpu \ --version="25.3.0-rc.2" \ --namespace nvidia-dra-driver \ --create-namespace \ --values dra-driver-values.yaml
Schritt 4: Überprüfen Sie die DRA-Installation
-
Stellen Sie sicher, dass die DRA-API-Ressourcen verfügbar sind:
kubectl api-resources | grep resource.k8s.io/v1beta1Das Folgende ist die erwartete Ausgabe:
deviceclasses resource.k8s.io/v1beta1 false DeviceClass resourceclaims resource.k8s.io/v1beta1 true ResourceClaim resourceclaimtemplates resource.k8s.io/v1beta1 true ResourceClaimTemplate resourceslices resource.k8s.io/v1beta1 false ResourceSlice -
Überprüfen Sie die verfügbaren Geräteklassen:
kubectl get deviceclassesDas Folgende ist ein Beispiel für die erwartete Ausgabe:
NAME AGE compute-domain-daemon.nvidia.com 4h39m compute-domain-default-channel.nvidia.com 4h39m gpu.nvidia.com 4h39m mig.nvidia.com 4h39mWenn eine neu erstellte G6-GPU-Instance mit aktiviertem DRA Ihrem Amazon EKS-Cluster beitritt, werden die folgenden Aktionen ausgeführt:
-
Der NVIDIA DRA-Treiber erkennt automatisch die A10G-GPU und erstellt zwei
resourceslicesauf diesem Knoten. -
Der
gpu.nvidia.comSlice registriert das physische A10G-GPU-Gerät mit seinen Spezifikationen (Speicher, Rechenleistung und mehr). -
Da A10G keine MIG-Partitionierung unterstützt, erstellt der
compute-domain.nvidia.comSlice eine einzelne Rechendomäne, die den gesamten Rechenkontext der GPU darstellt. -
Diese
resourcesliceswerden dann auf dem Kubernetes-API-Server veröffentlicht, sodass die GPU-Ressourcen für die Planung zur Verfügung stehen.resourceclaimsDer DRA-Scheduler kann diese GPU nun intelligent Pods zuweisen, über
resourceclaimtemplatesdie GPU-Ressourcen angefordert werden. Dies ermöglicht eine flexiblere Ressourcenverwaltung im Vergleich zu herkömmlichen Geräte-Plug-in-Ansätzen. Dies geschieht automatisch ohne manuelles Eingreifen. Der Knoten wird einfach für GPU-Workloads verfügbar, sobald der DRA-Treiber den Ressourcenermittlungs- und Registrierungsprozess abgeschlossen hat.Wenn Sie den folgenden Befehl ausführen:
kubectl get resourceslicesDas Folgende ist ein Beispiel für die erwartete Ausgabe:
NAME NODE DRIVER POOL AGE ip-100-64-129-47.ec2.internal-compute-domain.nvidia.com-rwsts ip-100-64-129-47.ec2.internal compute-domain.nvidia.com ip-100-64-129-47.ec2.internal 35m ip-100-64-129-47.ec2.internal-gpu.nvidia.com-6kndg ip-100-64-129-47.ec2.internal gpu.nvidia.com ip-100-64-129-47.ec2.internal 35m
-
Fahren Sie fort mit Planen Sie eine einfache GPU-Arbeitslast mithilfe der dynamischen Ressourcenzuweisung.
Planen Sie eine einfache GPU-Arbeitslast mithilfe der dynamischen Ressourcenzuweisung
Gehen Sie wie folgt vor, um einen einfachen GPU-Workload mithilfe der dynamischen Ressourcenzuweisung (DRA) zu planen. Bevor Sie fortfahren, stellen Sie sicher, dass Sie den Anweisungen gefolgt sindRichten Sie eine dynamische Ressourcenzuweisung für eine erweiterte GPU-Verwaltung ein.
-
Erstellen Sie eine Basisdatei
ResourceClaimTemplatefür die GPU-Zuweisung mit einer Datei mit dem Namenbasic-gpu-claim-template.yaml:--- apiVersion: v1 kind: Namespace metadata: name: gpu-test1 --- apiVersion: resource.k8s.io/v1beta1 kind: ResourceClaimTemplate metadata: namespace: gpu-test1 name: single-gpu spec: spec: devices: requests: - name: gpu deviceClassName: gpu.nvidia.com -
Wenden Sie die Vorlage an:
kubectl apply -f basic-gpu-claim-template.yaml -
Überprüfen Sie den Status:
kubectl get resourceclaimtemplates -n gpu-test1Das Folgende ist eine Beispielausgabe:
NAME AGE single-gpu 9m16s -
Erstellen Sie einen Pod, der den verwendet,
ResourceClaimTemplatemit einer Datei namensbasic-gpu-pod.yaml:--- apiVersion: v1 kind: Pod metadata: namespace: gpu-test1 name: gpu-pod labels: app: pod spec: containers: - name: ctr0 image: ubuntu:22.04 command: ["bash", "-c"] args: ["nvidia-smi -L; trap 'exit 0' TERM; sleep 9999 & wait"] resources: claims: - name: gpu0 resourceClaims: - name: gpu0 resourceClaimTemplateName: single-gpu nodeSelector: NodeGroupType: gpu-dra nvidia.com/gpu.present: "true" tolerations: - key: "nvidia.com/gpu" operator: "Exists" effect: "NoSchedule" -
Wenden Sie den Pod an und überwachen Sie ihn:
kubectl apply -f basic-gpu-pod.yaml -
Überprüfe den Pod-Status:
kubectl get pod -n gpu-test1Im Folgenden finden Sie ein Beispiel für eine erwartete Ausgabe:
NAME READY STATUS RESTARTS AGE gpu-pod 1/1 Running 0 13m -
Überprüfen Sie den
ResourceClaimStatus:kubectl get resourceclaims -n gpu-test1Im Folgenden finden Sie ein Beispiel für eine erwartete Ausgabe:
NAME STATE AGE gpu-pod-gpu0-l76cg allocated,reserved 9m6s -
Sehen Sie sich die Pod-Logs an, um GPU-Informationen zu sehen:
kubectl logs gpu-pod -n gpu-test1Im Folgenden finden Sie ein Beispiel für eine erwartete Ausgabe:
GPU 0: NVIDIA L4 (UUID: GPU-da7c24d7-c7e3-ed3b-418c-bcecc32af7c5)
Weiter unter finden Sie GPU-Optimierungstechniken mit dynamischer Ressourcenzuweisung fortgeschrittenere GPU-Optimierungstechniken mit DRA.
GPU-Optimierungstechniken mit dynamischer Ressourcenzuweisung
Moderne GPU-Workloads erfordern ein ausgeklügeltes Ressourcenmanagement, um eine optimale Auslastung und Kosteneffizienz zu erreichen. DRA ermöglicht mehrere fortschrittliche Optimierungstechniken, die auf unterschiedliche Anwendungsfälle und Hardwarefunktionen zugeschnitten sind:
-
Time-slicingermöglicht es mehreren Workloads, GPU-Rechenressourcen im Laufe der Zeit gemeinsam zu nutzen, wodurch es sich ideal für Inferenz-Workloads mit sporadischer GPU-Nutzung eignet. Ein Beispiel finden Sie unter Optimieren Sie GPU-Workloads mit Time-Slicing.
-
Multi-Process Service (MPS) ermöglicht die gleichzeitige Ausführung mehrerer CUDA-Prozesse auf einer einzigen GPU mit besserer Isolierung als Time-Slicing. Ein Beispiel finden Sie unter Optimieren Sie GPU-Workloads mit MPS.
-
Multi-Instance GPU (MIG) bietet Partitionierung auf Hardwareebene und erstellt isolierte GPU-Instanzen mit dedizierten Rechen- und Speicherressourcen. Ein Beispiel finden Sie unter Optimieren Sie GPU-Workloads mit GPU Multi-Instance.
-
Internode Memory Exchange (IMEX) ermöglicht die speicherkohärente Kommunikation zwischen Knoten für verteiltes Training auf NVIDIA GB200-Systemen. Ein Beispiel finden Sie unter Optimieren Sie GPU-Workloads mit IMEX mithilfe von GB200 P6e-Instances.
Diese Techniken können die Ressourcennutzung erheblich verbessern. Unternehmen berichten, dass die GPU-Auslastung bei herkömmlicher Zuweisung von 30-40% auf 80-90% bei optimierten Strategien zur gemeinsamen Nutzung gestiegen ist. Die Wahl der Technik hängt von den Merkmalen der Arbeitslast, den Isolationsanforderungen und den Hardwarefunktionen ab.
Optimieren Sie GPU-Workloads mit Time-Slicing
Time-slicing ermöglicht es mehreren Workloads, GPU-Rechenressourcen gemeinsam zu nutzen, indem sie so geplant werden, dass sie sequentiell auf derselben physischen GPU ausgeführt werden. Es ist ideal für Inferenz-Workloads mit sporadischer GPU-Nutzung.
Führen Sie die folgenden Schritte aus.
-
Definieren Sie eine
ResourceClaimTemplatefür Time-Slicing mit einer Datei namens:timeslicing-claim-template.yaml--- apiVersion: v1 kind: Namespace metadata: name: timeslicing-gpu --- apiVersion: resource.k8s.io/v1beta1 kind: ResourceClaimTemplate metadata: name: timeslicing-gpu-template namespace: timeslicing-gpu spec: spec: devices: requests: - name: shared-gpu deviceClassName: gpu.nvidia.com config: - requests: ["shared-gpu"] opaque: driver: gpu.nvidia.com parameters: apiVersion: resource.nvidia.com/v1beta1 kind: GpuConfig sharing: strategy: TimeSlicing -
Definieren Sie einen Pod mithilfe von Timeslicing mit einer Datei namens:
timeslicing-pod.yaml--- # Pod 1 - Inference workload apiVersion: v1 kind: Pod metadata: name: inference-pod-1 namespace: timeslicing-gpu labels: app: gpu-inference spec: restartPolicy: Never containers: - name: inference-container image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["python", "-c"] args: - | import torch import time import os print(f"=== POD 1 STARTING ===") print(f"GPU available: {torch.cuda.is_available()}") print(f"GPU count: {torch.cuda.device_count()}") if torch.cuda.is_available(): device = torch.cuda.current_device() print(f"Current GPU: {torch.cuda.get_device_name(device)}") print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB") # Simulate inference workload for i in range(20): x = torch.randn(1000, 1000).cuda() y = torch.mm(x, x.t()) print(f"Pod 1 - Iteration {i+1} completed at {time.strftime('%H:%M:%S')}") time.sleep(60) else: print("No GPU available!") time.sleep(5) resources: claims: - name: shared-gpu-claim resourceClaims: - name: shared-gpu-claim resourceClaimTemplateName: timeslicing-gpu-template nodeSelector: NodeGroupType: "gpu-dra" nvidia.com/gpu.present: "true" tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule --- # Pod 2 - Training workload apiVersion: v1 kind: Pod metadata: name: training-pod-2 namespace: timeslicing-gpu labels: app: gpu-training spec: restartPolicy: Never containers: - name: training-container image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["python", "-c"] args: - | import torch import time import os print(f"=== POD 2 STARTING ===") print(f"GPU available: {torch.cuda.is_available()}") print(f"GPU count: {torch.cuda.device_count()}") if torch.cuda.is_available(): device = torch.cuda.current_device() print(f"Current GPU: {torch.cuda.get_device_name(device)}") print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB") # Simulate training workload with heavier compute for i in range(15): x = torch.randn(2000, 2000).cuda() y = torch.mm(x, x.t()) loss = torch.sum(y) print(f"Pod 2 - Training step {i+1}, Loss: {loss.item():.2f} at {time.strftime('%H:%M:%S')}") time.sleep(5) else: print("No GPU available!") time.sleep(60) resources: claims: - name: shared-gpu-claim-2 resourceClaims: - name: shared-gpu-claim-2 resourceClaimTemplateName: timeslicing-gpu-template nodeSelector: NodeGroupType: "gpu-dra" nvidia.com/gpu.present: "true" tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule -
Wenden Sie die Vorlage und den Pod an:
kubectl apply -f timeslicing-claim-template.yaml kubectl apply -f timeslicing-pod.yaml -
Überwachen Sie die Ressourcenansprüche:
kubectl get resourceclaims -n timeslicing-gpu -wDas Folgende ist eine Beispielausgabe:
NAME STATE AGE inference-pod-1-shared-gpu-claim-9p97x allocated,reserved 21s training-pod-2-shared-gpu-claim-2-qghnb pending 21s inference-pod-1-shared-gpu-claim-9p97x pending 105s training-pod-2-shared-gpu-claim-2-qghnb pending 105s inference-pod-1-shared-gpu-claim-9p97x pending 105s training-pod-2-shared-gpu-claim-2-qghnb allocated,reserved 105s inference-pod-1-shared-gpu-claim-9p97x pending 105s
Erster Pod (inference-pod-1)
-
Bundesland:
allocated,reserved -
Das heißt: DRA hat eine verfügbare GPU gefunden und sie für diesen Pod reserviert
-
Pod-Status: Beginnt sofort zu laufen
Zweiter Pod (training-pod-2)
-
Bundesland:
pending -
Bedeutung: Warten darauf, dass DRA Time-Slicing auf derselben GPU konfiguriert
-
Pod-Status: Wartet auf einen Termin
-
Der Staat wechselt von
pendingbisallocated,reservedbisrunning
Optimieren Sie GPU-Workloads mit MPS
Multi-Process Service (MPS) ermöglicht die gleichzeitige Ausführung mehrerer CUDA-Kontexte auf einer einzigen GPU mit besserer Isolierung als Time-Slicing.
Führen Sie die folgenden Schritte aus.
-
Definieren Sie eine
ResourceClaimTemplatefür MPS mit einer Datei namensmps-claim-template.yaml:--- apiVersion: v1 kind: Namespace metadata: name: mps-gpu --- apiVersion: resource.k8s.io/v1beta1 kind: ResourceClaimTemplate metadata: name: mps-gpu-template namespace: mps-gpu spec: spec: devices: requests: - name: shared-gpu deviceClassName: gpu.nvidia.com config: - requests: ["shared-gpu"] opaque: driver: gpu.nvidia.com parameters: apiVersion: resource.nvidia.com/v1beta1 kind: GpuConfig sharing: strategy: MPS -
Definieren Sie einen Pod, der MPS verwendet, mit einer Datei namens
mps-pod.yaml:--- # Single Pod with Multiple Containers sharing GPU via MPS apiVersion: v1 kind: Pod metadata: name: mps-multi-container-pod namespace: mps-gpu labels: app: mps-demo spec: restartPolicy: Never containers: # Container 1 - Inference workload - name: inference-container image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["python", "-c"] args: - | import torch import torch.nn as nn import time import os print(f"=== INFERENCE CONTAINER STARTING ===") print(f"Process ID: {os.getpid()}") print(f"GPU available: {torch.cuda.is_available()}") print(f"GPU count: {torch.cuda.device_count()}") if torch.cuda.is_available(): device = torch.cuda.current_device() print(f"Current GPU: {torch.cuda.get_device_name(device)}") print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB") # Create inference model model = nn.Sequential( nn.Linear(1000, 500), nn.ReLU(), nn.Linear(500, 100) ).cuda() # Run inference for i in range(1, 999999): with torch.no_grad(): x = torch.randn(128, 1000).cuda() output = model(x) result = torch.sum(output) print(f"Inference Container PID {os.getpid()}: Batch {i}, Result: {result.item():.2f} at {time.strftime('%H:%M:%S')}") time.sleep(2) else: print("No GPU available!") time.sleep(60) resources: claims: - name: shared-gpu-claim request: shared-gpu # Container 2 - Training workload - name: training-container image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["python", "-c"] args: - | import torch import torch.nn as nn import time import os print(f"=== TRAINING CONTAINER STARTING ===") print(f"Process ID: {os.getpid()}") print(f"GPU available: {torch.cuda.is_available()}") print(f"GPU count: {torch.cuda.device_count()}") if torch.cuda.is_available(): device = torch.cuda.current_device() print(f"Current GPU: {torch.cuda.get_device_name(device)}") print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1024**3:.1f} GB") # Create training model model = nn.Sequential( nn.Linear(2000, 1000), nn.ReLU(), nn.Linear(1000, 500), nn.ReLU(), nn.Linear(500, 10) ).cuda() criterion = nn.MSELoss() optimizer = torch.optim.Adam(model.parameters(), lr=0.001) # Run training for epoch in range(1, 999999): x = torch.randn(64, 2000).cuda() target = torch.randn(64, 10).cuda() optimizer.zero_grad() output = model(x) loss = criterion(output, target) loss.backward() optimizer.step() print(f"Training Container PID {os.getpid()}: Epoch {epoch}, Loss: {loss.item():.4f} at {time.strftime('%H:%M:%S')}") time.sleep(3) else: print("No GPU available!") time.sleep(60) resources: claims: - name: shared-gpu-claim request: shared-gpu resourceClaims: - name: shared-gpu-claim resourceClaimTemplateName: mps-gpu-template nodeSelector: NodeGroupType: "gpu-dra" nvidia.com/gpu.present: "true" tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule -
Wenden Sie die Vorlage an und erstellen Sie mehrere MPS-Pods:
kubectl apply -f mps-claim-template.yaml kubectl apply -f mps-pod.yaml -
Überwachen Sie die Ressourcenansprüche:
kubectl get resourceclaims -n mps-gpu -wDas Folgende ist eine Beispielausgabe:
NAME STATE AGE mps-multi-container-pod-shared-gpu-claim-2p9kx allocated,reserved 86s
Diese Konfiguration demonstriert echte GPU-Sharing mithilfe des Multi-Process NVIDIA-Dienstes (MPS) durch dynamische Ressourcenzuweisung (DRA). Im Gegensatz zum Time-Slicing, bei dem die Workloads nacheinander die GPU verwenden, ermöglicht MPS, dass beide Container gleichzeitig auf derselben physischen GPU ausgeführt werden. Die wichtigste Erkenntnis ist, dass für die gemeinsame Nutzung von DRA MPS mehrere Container in einem einzelnen Pod erforderlich sind, nicht mehrere separate Pods. Bei der Bereitstellung weist der DRA-Treiber dem Pod einen ResourceClaim zu und konfiguriert MPS automatisch, sodass sowohl der Inferenz- als auch der Trainingscontainer gleichzeitig ausgeführt werden können.
Jeder Container erhält seinen eigenen isolierten GPU-Speicherplatz und seine eigenen Rechenressourcen, wobei der MPS-Daemon den Zugriff auf die zugrunde liegende Hardware koordiniert. Sie können überprüfen, ob dies funktioniert, indem Sie wie folgt vorgehen:
-
Überprüfung
nvidia-smi, bei der beide Container als M+C (MPS + Compute) -Prozesse angezeigt werden, die sich dasselbe GPU-Gerät teilen. -
Überwachung der Logs aus beiden Containern, wobei verschachtelte Zeitstempel angezeigt werden, die eine gleichzeitige Ausführung belegen.
Dieser Ansatz maximiert die GPU-Auslastung, da ergänzende Workloads die teure GPU-Hardware effizient gemeinsam nutzen können, anstatt sie durch einen einzelnen Prozess ungenutzt zu lassen.
Container 1: Inferenzcontainer
root@mps-multi-container-pod:/workspace# nvidia-smi
Wed Jul 16 21:09:30 2025
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 570.158.01 Driver Version: 570.158.01 CUDA Version: 12.9 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA L4 On | 00000000:35:00.0 Off | 0 |
| N/A 48C P0 28W / 72W | 597MiB / 23034MiB | 0% E. Process |
| | | N/A |
+-----------------------------------------+------------------------+----------------------+
+-----------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
| 0 N/A N/A 1 M+C python 246MiB |
+-----------------------------------------------------------------------------------------+
Behälter 2: Trainingscontainer
root@mps-multi-container-pod:/workspace# nvidia-smi
Wed Jul 16 21:16:00 2025
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 570.158.01 Driver Version: 570.158.01 CUDA Version: 12.9 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA L4 On | 00000000:35:00.0 Off | 0 |
| N/A 51C P0 28W / 72W | 597MiB / 23034MiB | 0% E. Process |
| | | N/A |
+-----------------------------------------+------------------------+----------------------+
+-----------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
| 0 N/A N/A 1 M+C python 314MiB |
+-----------------------------------------------------------------------------------------+
Optimieren Sie GPU-Workloads mit GPU Multi-Instance
Multi-instance GPU (MIG) bietet Partitionierung auf Hardwareebene und erstellt isolierte GPU-Instanzen mit dedizierten Rechen- und Speicherressourcen.
Für die Verwendung der dynamischen MIG-Partitionierung mit verschiedenen Profilen ist der NVIDIA GPU Operator erforderlich. WITH0—REBOOT=true in der MIG Manager-Konfiguration für erfolgreiche MIG-Bereitstellungen unerlässlich.
Sie benötigen sowohl den NVIDIA DRA-Treiber
Schritt 1: Stellen Sie NVIDIA GPU Operator bereit
-
Fügen Sie das NVIDIA GPU Operator-Repository hinzu:
helm repo add nvidia https://nvidia.github.io/gpu-operator helm repo update -
Erstellen Sie eine
gpu-operator-values.yamlDatei:driver: enabled: false mig: strategy: mixed migManager: enabled: true env: - name: WITH_REBOOT value: "true" config: create: true name: custom-mig-parted-configs default: "all-disabled" data: config.yaml: |- version: v1 mig-configs: all-disabled: - devices: all mig-enabled: false # P4D profiles (A100 40GB) p4d-half-balanced: - devices: [0, 1, 2, 3] mig-enabled: true mig-devices: "1g.5gb": 2 "2g.10gb": 1 "3g.20gb": 1 - devices: [4, 5, 6, 7] mig-enabled: false # P4DE profiles (A100 80GB) p4de-half-balanced: - devices: [0, 1, 2, 3] mig-enabled: true mig-devices: "1g.10gb": 2 "2g.20gb": 1 "3g.40gb": 1 - devices: [4, 5, 6, 7] mig-enabled: false devicePlugin: enabled: true config: name: "" create: false default: "" toolkit: enabled: true nfd: enabled: true gfd: enabled: true dcgmExporter: enabled: true serviceMonitor: enabled: true interval: 15s honorLabels: false additionalLabels: release: kube-prometheus-stack nodeStatusExporter: enabled: false operator: defaultRuntime: containerd runtimeClass: nvidia resources: limits: cpu: 500m memory: 350Mi requests: cpu: 200m memory: 100Mi daemonsets: tolerations: - key: "nvidia.com/gpu" operator: "Exists" effect: "NoSchedule" nodeSelector: accelerator: nvidia priorityClassName: system-node-critical -
Installieren Sie GPU Operator mithilfe der
gpu-operator-values.yamlDatei:helm install gpu-operator nvidia/gpu-operator \ --namespace gpu-operator \ --create-namespace \ --version v25.3.1 \ --values gpu-operator-values.yamlDieses Helm-Diagramm stellt die folgenden Komponenten und mehrere MIG-Profile bereit:
-
Geräte-Plugin (GPU-Ressourcenplanung)
-
DCGM Exporter (GPU-Metriken und Überwachung)
-
Erkennung von Node-Funktionen (NFD — Hardwarekennzeichnung)
-
Erkennung von GPU-Funktionen (GFD — GPU-specific Kennzeichnung)
-
MIG Manager (Multi-instance GPU-Partitionierung)
-
Container-Toolkit (GPU-Container-Laufzeit)
-
Operator Controller (Lebenszyklusmanagement)
-
-
Überprüfen Sie die Bereitstellungs-Pods:
kubectl get pods -n gpu-operatorDas Folgende ist eine Beispielausgabe:
NAME READY STATUS RESTARTS AGE gpu-feature-discovery-27rdq 1/1 Running 0 3h31m gpu-operator-555774698d-48brn 1/1 Running 0 4h8m nvidia-container-toolkit-daemonset-sxmh9 1/1 Running 1 (3h32m ago) 4h1m nvidia-cuda-validator-qb77g 0/1 Completed 0 3h31m nvidia-dcgm-exporter-cvzd7 1/1 Running 0 3h31m nvidia-device-plugin-daemonset-5ljm5 1/1 Running 0 3h31m nvidia-gpu-operator-node-feature-discovery-gc-67f66fc557-q5wkt 1/1 Running 0 4h8m nvidia-gpu-operator-node-feature-discovery-master-5d8ffddcsl6s6 1/1 Running 0 4h8m nvidia-gpu-operator-node-feature-discovery-worker-6t4w7 1/1 Running 1 (3h32m ago) 4h1m nvidia-gpu-operator-node-feature-discovery-worker-9w7g8 1/1 Running 0 4h8m nvidia-gpu-operator-node-feature-discovery-worker-k5fgs 1/1 Running 0 4h8m nvidia-mig-manager-zvf54 1/1 Running 1 (3h32m ago) 3h35m -
Erstellen Sie einen Amazon EKS-Cluster mit einer von P4de verwalteten Knotengruppe, um die MIG-Beispiele zu testen:
apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: dra-eks-cluster region: us-east-1 version: '1.33' managedNodeGroups: # P4DE MIG Node Group with Capacity Block Reservation - name: p4de-mig-nodes amiFamily: AmazonLinux2023 instanceType: p4de.24xlarge # Capacity settings desiredCapacity: 0 minSize: 0 maxSize: 1 # Use specific subnet in us-east-1b for capacity reservation subnets: - us-east-1b # AL2023 NodeConfig for RAID0 local storage only nodeadmConfig: apiVersion: node.eks.aws/v1alpha1 kind: NodeConfig spec: instance: localStorage: strategy: RAID0 # Node labels for MIG configuration labels: nvidia.com/gpu.present: "true" nvidia.com/gpu.product: "A100-SXM4-80GB" nvidia.com/mig.config: "p4de-half-balanced" node-type: "p4de" vpc.amazonaws.com/efa.present: "true" accelerator: "nvidia" # Node taints taints: - key: nvidia.com/gpu value: "true" effect: NoSchedule # EFA support efaEnabled: true # Placement group for high-performance networking placementGroup: groupName: p4de-placement-group strategy: cluster # Capacity Block Reservation (CBR) # Ensure CBR ID matches the subnet AZ with the Nodegroup subnet spot: false capacityReservation: capacityReservationTarget: capacityReservationId: "cr-abcdefghij" # Replace with your capacity reservation IDNVIDIA GPU Operator verwendet das Label, das den Knoten hinzugefügt wurde,
nvidia.com/mig.config: "p4de-half-balanced"und partitioniert die GPU mit dem angegebenen Profil. -
Melden Sie sich bei der
p4deInstanz an. -
Führen Sie den folgenden Befehl aus:
nvidia-smi -LSie sollten die folgende Beispielausgabe sehen:
[root@ip-100-64-173-145 bin]# nvidia-smi -L GPU 0: NVIDIA A100-SXM4-80GB (UUID: GPU-ab52e33c-be48-38f2-119e-b62b9935925a) MIG 3g.40gb Device 0: (UUID: MIG-da972af8-a20a-5f51-849f-bc0439f7970e) MIG 2g.20gb Device 1: (UUID: MIG-7f9768b7-11a6-5de9-a8aa-e9c424400da4) MIG 1g.10gb Device 2: (UUID: MIG-498adad6-6cf7-53af-9d1a-10cfd1fa53b2) MIG 1g.10gb Device 3: (UUID: MIG-3f55ef65-1991-571a-ac50-0dbf50d80c5a) GPU 1: NVIDIA A100-SXM4-80GB (UUID: GPU-0eabeccc-7498-c282-0ac7-d3c09f6af0c8) MIG 3g.40gb Device 0: (UUID: MIG-80543849-ea3b-595b-b162-847568fe6e0e) MIG 2g.20gb Device 1: (UUID: MIG-3af1958f-fac4-59f1-8477-9f8d08c55029) MIG 1g.10gb Device 2: (UUID: MIG-401088d2-716f-527b-a970-b1fc7a4ac6b2) MIG 1g.10gb Device 3: (UUID: MIG-8c56c75e-5141-501c-8f43-8cf22f422569) GPU 2: NVIDIA A100-SXM4-80GB (UUID: GPU-1c7a1289-243f-7872-a35c-1d2d8af22dd0) MIG 3g.40gb Device 0: (UUID: MIG-e9b44486-09fc-591a-b904-0d378caf2276) MIG 2g.20gb Device 1: (UUID: MIG-ded93941-9f64-56a3-a9b1-a129c6edf6e4) MIG 1g.10gb Device 2: (UUID: MIG-6c317d83-a078-5c25-9fa3-c8308b379aa1) MIG 1g.10gb Device 3: (UUID: MIG-2b070d39-d4e9-5b11-bda6-e903372e3d08) GPU 3: NVIDIA A100-SXM4-80GB (UUID: GPU-9a6250e2-5c59-10b7-2da8-b61d8a937233) MIG 3g.40gb Device 0: (UUID: MIG-20e3cd87-7a57-5f1b-82e7-97b14ab1a5aa) MIG 2g.20gb Device 1: (UUID: MIG-04430354-1575-5b42-95f4-bda6901f1ace) MIG 1g.10gb Device 2: (UUID: MIG-d62ec8b6-e097-5e99-a60c-abf8eb906f91) MIG 1g.10gb Device 3: (UUID: MIG-fce20069-2baa-5dd4-988a-cead08348ada) GPU 4: NVIDIA A100-SXM4-80GB (UUID: GPU-5d09daf0-c2eb-75fd-3919-7ad8fafa5f86) GPU 5: NVIDIA A100-SXM4-80GB (UUID: GPU-99194e04-ab2a-b519-4793-81cb2e8e9179) GPU 6: NVIDIA A100-SXM4-80GB (UUID: GPU-c1a1910f-465a-e16f-5af1-c6aafe499cd6) GPU 7: NVIDIA A100-SXM4-80GB (UUID: GPU-c2cfafbc-fd6e-2679-e955-2a9e09377f78)
NVIDIA GPU Operator hat das p4de-half-balanced MIG-Profil erfolgreich auf Ihre P4DE-Instance angewendet und GPU-Partitionen auf Hardwareebene wie konfiguriert erstellt. So funktioniert die Partitionierung:
Der GPU-Operator hat diese Konfiguration aus Ihrem eingebetteten MIG-Profil übernommen:
p4de-half-balanced:
- devices: [0, 1, 2, 3] # First 4 GPUs: MIG enabled
mig-enabled: true
mig-devices:
"1g.10gb": 2 # 2x small instances (10GB each)
"2g.20gb": 1 # 1x medium instance (20GB)
"3g.40gb": 1 # 1x large instance (40GB)
- devices: [4, 5, 6, 7] # Last 4 GPUs: Full GPUs
mig-enabled: false
Aus Ihrer nvidia-smi -L Ausgabe hat der GPU-Operator Folgendes erstellt:
-
MIG-enabled GPUs (0-3): hardwarepartitioniert
-
GRAFIKPROZESSOR 0: NVIDIA A100-SXM4-80GB
-
MIG 3g.40gb Device 0 — Große Workloads (40 GB Arbeitsspeicher, 42 SMs)
-
MIG 2g.20gb Gerät 1 — Mittlere Arbeitslasten (20 GB Arbeitsspeicher, 28 SMs)
-
MIG 1g.10gb Gerät 2 — Kleine Workloads (10 GB Arbeitsspeicher, 14 SMs)
-
MIG 1g.10gb Gerät 3 — Kleine Workloads (10 GB Arbeitsspeicher, 14 SMs)
-
-
GPU 1: NVIDIA A100-SXM4-80GB
-
MIG 3g.40gb Gerät 0 — Identisches Partitionslayout
-
MIG 2g.20gb Gerät 1
-
MIG 1g.10gb Gerät 2
-
MIG 1g.10gb Gerät 3
-
-
GPU 2 und GPU 3 — Das gleiche Muster wie GPU 0 und GPU 1
-
-
Vollständige GPUs (4-7): Keine MIG-Partitionierung
-
GPU 4: NVIDIA A100-SXM4-80GB — Volle 80-GB-GPU
-
GPU 5: NVIDIA A100-SXM4-80GB — Volle 80-GB-GPU
-
GPU 6: NVIDIA A100-SXM4-80GB — Volle 80-GB-GPU
-
GPU 7: NVIDIA A100-SXM4-80GB — Volle 80-GB-GPU
-
Sobald der NVIDIA-GPU-Operator die MIG-Partitionen erstellt hat, erkennt der NVIDIA DRA-Treiber diese hardwareisolierten Instanzen automatisch und stellt sie für die dynamische Ressourcenzuweisung in Kubernetes zur Verfügung. Der DRA-Treiber erkennt jede MIG-Instanz mit ihrem spezifischen Profil (1g.10gb, 2g.20gb, 3g.40gb) und macht sie über die Geräteklasse als planbare Ressourcen verfügbar. mig.nvidia.com
Der DRA-Treiber überwacht kontinuierlich die MIG-Topologie und führt ein Inventar der verfügbaren Instanzen auf allen GPUs. Wenn ein Pod ein bestimmtes MIG-Profil über a anfordertResourceClaimTemplate, wählt der DRA-Treiber intelligent eine geeignete MIG-Instance aus jeder verfügbaren GPU aus und ermöglicht so eine echte Mehrmandantenfähigkeit auf Hardwareebene. Durch diese dynamische Zuweisung können mehrere isolierte Workloads gleichzeitig auf derselben physischen GPU ausgeführt werden, während strenge Ressourcengrenzen und Leistungsgarantien eingehalten werden.
Schritt 2: Testen Sie die MIG-Ressourcenzuweisung
Lassen Sie uns nun anhand einiger Beispiele demonstrieren, wie DRA MIG-Instanzen dynamisch verschiedenen Workloads zuweist. Stellen Sie die Pods bereit resourceclaimtemplates und testen Sie sie, um zu sehen, wie der DRA-Treiber Workloads auf die verfügbaren MIG-Partitionen verteilt, sodass mehrere Container GPU-Ressourcen mit Isolierung auf Hardwareebene gemeinsam nutzen können.
-
Erstellen Sie,
mig-claim-template.yamlum die MIG einzuschließen:resourceclaimtemplatesapiVersion: v1 kind: Namespace metadata: name: mig-gpu --- # Template for 3g.40gb MIG instance (Large training) apiVersion: resource.k8s.io/v1beta1 kind: ResourceClaimTemplate metadata: name: mig-large-template namespace: mig-gpu spec: spec: devices: requests: - name: mig-large deviceClassName: mig.nvidia.com selectors: - cel: expression: | device.attributes['gpu.nvidia.com'].profile == '3g.40gb' --- # Template for 2g.20gb MIG instance (Medium training) apiVersion: resource.k8s.io/v1beta1 kind: ResourceClaimTemplate metadata: name: mig-medium-template namespace: mig-gpu spec: spec: devices: requests: - name: mig-medium deviceClassName: mig.nvidia.com selectors: - cel: expression: | device.attributes['gpu.nvidia.com'].profile == '2g.20gb' --- # Template for 1g.10gb MIG instance (Small inference) apiVersion: resource.k8s.io/v1beta1 kind: ResourceClaimTemplate metadata: name: mig-small-template namespace: mig-gpu spec: spec: devices: requests: - name: mig-small deviceClassName: mig.nvidia.com selectors: - cel: expression: | device.attributes['gpu.nvidia.com'].profile == '1g.10gb' -
Wenden Sie die drei Vorlagen an:
kubectl apply -f mig-claim-template.yaml -
Führen Sie den folgenden Befehl aus:
kubectl get resourceclaimtemplates -n mig-gpuDas Folgende ist eine Beispielausgabe:
NAME AGE mig-large-template 71m mig-medium-template 71m mig-small-template 71m -
Erstellen Sie
mig-pod.yaml, um mehrere Jobs zu planen und dies zu nutzenresourceclaimtemplates:--- # ConfigMap containing Python scripts for MIG pods apiVersion: v1 kind: ConfigMap metadata: name: mig-scripts-configmap namespace: mig-gpu data: large-training-script.py: | import torch import torch.nn as nn import torch.optim as optim import time import os print(f"=== LARGE TRAINING POD (3g.40gb) ===") print(f"Process ID: {os.getpid()}") print(f"GPU available: {torch.cuda.is_available()}") print(f"GPU count: {torch.cuda.device_count()}") if torch.cuda.is_available(): device = torch.cuda.current_device() print(f"Using GPU: {torch.cuda.get_device_name(device)}") print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1e9:.1f} GB") # Large model for 3g.40gb instance model = nn.Sequential( nn.Linear(2048, 1024), nn.ReLU(), nn.Linear(1024, 512), nn.ReLU(), nn.Linear(512, 256), nn.ReLU(), nn.Linear(256, 10) ).cuda() optimizer = optim.Adam(model.parameters()) criterion = nn.CrossEntropyLoss() print(f"Model parameters: {sum(p.numel() for p in model.parameters())}") # Training loop for epoch in range(100): # Large batch for 3g.40gb x = torch.randn(256, 2048).cuda() y = torch.randint(0, 10, (256,)).cuda() optimizer.zero_grad() output = model(x) loss = criterion(output, y) loss.backward() optimizer.step() if epoch % 10 == 0: print(f"Large Training - Epoch {epoch}, Loss: {loss.item():.4f}, GPU Memory: {torch.cuda.memory_allocated()/1e9:.2f}GB") time.sleep(3) print("Large training completed on 3g.40gb MIG instance") medium-training-script.py: | import torch import torch.nn as nn import torch.optim as optim import time import os print(f"=== MEDIUM TRAINING POD (2g.20gb) ===") print(f"Process ID: {os.getpid()}") print(f"GPU available: {torch.cuda.is_available()}") print(f"GPU count: {torch.cuda.device_count()}") if torch.cuda.is_available(): device = torch.cuda.current_device() print(f"Using GPU: {torch.cuda.get_device_name(device)}") print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1e9:.1f} GB") # Medium model for 2g.20gb instance model = nn.Sequential( nn.Linear(1024, 512), nn.ReLU(), nn.Linear(512, 256), nn.ReLU(), nn.Linear(256, 10) ).cuda() optimizer = optim.Adam(model.parameters()) criterion = nn.CrossEntropyLoss() print(f"Model parameters: {sum(p.numel() for p in model.parameters())}") # Training loop for epoch in range(100): # Medium batch for 2g.20gb x = torch.randn(128, 1024).cuda() y = torch.randint(0, 10, (128,)).cuda() optimizer.zero_grad() output = model(x) loss = criterion(output, y) loss.backward() optimizer.step() if epoch % 10 == 0: print(f"Medium Training - Epoch {epoch}, Loss: {loss.item():.4f}, GPU Memory: {torch.cuda.memory_allocated()/1e9:.2f}GB") time.sleep(4) print("Medium training completed on 2g.20gb MIG instance") small-inference-script.py: | import torch import torch.nn as nn import time import os print(f"=== SMALL INFERENCE POD (1g.10gb) ===") print(f"Process ID: {os.getpid()}") print(f"GPU available: {torch.cuda.is_available()}") print(f"GPU count: {torch.cuda.device_count()}") if torch.cuda.is_available(): device = torch.cuda.current_device() print(f"Using GPU: {torch.cuda.get_device_name(device)}") print(f"GPU Memory: {torch.cuda.get_device_properties(device).total_memory / 1e9:.1f} GB") # Small model for 1g.10gb instance model = nn.Sequential( nn.Linear(512, 256), nn.ReLU(), nn.Linear(256, 10) ).cuda() print(f"Model parameters: {sum(p.numel() for p in model.parameters())}") # Inference loop for i in range(200): with torch.no_grad(): # Small batch for 1g.10gb x = torch.randn(32, 512).cuda() output = model(x) prediction = torch.argmax(output, dim=1) if i % 20 == 0: print(f"Small Inference - Batch {i}, Predictions: {prediction[:5].tolist()}, GPU Memory: {torch.cuda.memory_allocated()/1e9:.2f}GB") time.sleep(2) print("Small inference completed on 1g.10gb MIG instance") --- # Pod 1: Large training workload (3g.40gb) apiVersion: v1 kind: Pod metadata: name: mig-large-training-pod namespace: mig-gpu labels: app: mig-large-training workload-type: training spec: restartPolicy: Never containers: - name: large-training-container image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["python", "/scripts/large-training-script.py"] volumeMounts: - name: script-volume mountPath: /scripts readOnly: true resources: claims: - name: mig-large-claim resourceClaims: - name: mig-large-claim resourceClaimTemplateName: mig-large-template nodeSelector: node.kubernetes.io/instance-type: p4de.24xlarge nvidia.com/gpu.present: "true" tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule volumes: - name: script-volume configMap: name: mig-scripts-configmap defaultMode: 0755 --- # Pod 2: Medium training workload (2g.20gb) - can run on SAME GPU as Pod 1 apiVersion: v1 kind: Pod metadata: name: mig-medium-training-pod namespace: mig-gpu labels: app: mig-medium-training workload-type: training spec: restartPolicy: Never containers: - name: medium-training-container image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["python", "/scripts/medium-training-script.py"] volumeMounts: - name: script-volume mountPath: /scripts readOnly: true resources: claims: - name: mig-medium-claim resourceClaims: - name: mig-medium-claim resourceClaimTemplateName: mig-medium-template nodeSelector: node.kubernetes.io/instance-type: p4de.24xlarge nvidia.com/gpu.present: "true" tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule volumes: - name: script-volume configMap: name: mig-scripts-configmap defaultMode: 0755 --- # Pod 3: Small inference workload (1g.10gb) - can run on SAME GPU as Pod 1 & 2 apiVersion: v1 kind: Pod metadata: name: mig-small-inference-pod namespace: mig-gpu labels: app: mig-small-inference workload-type: inference spec: restartPolicy: Never containers: - name: small-inference-container image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["python", "/scripts/small-inference-script.py"] volumeMounts: - name: script-volume mountPath: /scripts readOnly: true resources: claims: - name: mig-small-claim resourceClaims: - name: mig-small-claim resourceClaimTemplateName: mig-small-template nodeSelector: node.kubernetes.io/instance-type: p4de.24xlarge nvidia.com/gpu.present: "true" tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule volumes: - name: script-volume configMap: name: mig-scripts-configmap defaultMode: 0755 -
Wenden Sie diese Spezifikation an, die drei Pods bereitstellen sollte:
kubctl apply -f mig-pod.yamlDiese Pods sollten vom DRA-Treiber geplant werden.
-
Überprüfen Sie die Pod-Protokolle des DRA-Treibers und Sie werden eine Ausgabe sehen, die der folgenden ähnelt:
I0717 21:50:22.925811 1 driver.go:87] NodePrepareResource is called: number of claims: 1 I0717 21:50:22.932499 1 driver.go:129] Returning newly prepared devices for claim '933e9c72-6fd6-49c5-933c-a896407dc6d1': [&Device{RequestNames:[mig-large],PoolName:ip-100-64-173-145.ec2.internal,DeviceName:gpu-0-mig-9-4-4,CDIDeviceIDs:[k8s.gpu.nvidia.com/device=**gpu-0-mig-9-4-4**],}] I0717 21:50:23.186472 1 driver.go:87] NodePrepareResource is called: number of claims: 1 I0717 21:50:23.191226 1 driver.go:129] Returning newly prepared devices for claim '61e5ddd2-8c2e-4c19-93ae-d317fecb44a4': [&Device{RequestNames:[mig-medium],PoolName:ip-100-64-173-145.ec2.internal,DeviceName:gpu-2-mig-14-0-2,CDIDeviceIDs:[k8s.gpu.nvidia.com/device=**gpu-2-mig-14-0-2**],}] I0717 21:50:23.450024 1 driver.go:87] NodePrepareResource is called: number of claims: 1 I0717 21:50:23.455991 1 driver.go:129] Returning newly prepared devices for claim '1eda9b2c-2ea6-401e-96d0-90e9b3c111b5': [&Device{RequestNames:[mig-small],PoolName:ip-100-64-173-145.ec2.internal,DeviceName:gpu-1-mig-19-2-1,CDIDeviceIDs:[k8s.gpu.nvidia.com/device=**gpu-1-mig-19-2-1**],}] -
Überprüfen Sie das
resourceclaims, um den Pod-Status zu sehen:kubectl get resourceclaims -n mig-gpu -wDas Folgende ist eine Beispielausgabe:
NAME STATE AGE mig-large-training-pod-mig-large-claim-6dpn8 pending 0s mig-large-training-pod-mig-large-claim-6dpn8 pending 0s mig-large-training-pod-mig-large-claim-6dpn8 allocated,reserved 0s mig-medium-training-pod-mig-medium-claim-bk596 pending 0s mig-medium-training-pod-mig-medium-claim-bk596 pending 0s mig-medium-training-pod-mig-medium-claim-bk596 allocated,reserved 0s mig-small-inference-pod-mig-small-claim-d2t58 pending 0s mig-small-inference-pod-mig-small-claim-d2t58 pending 0s mig-small-inference-pod-mig-small-claim-d2t58 allocated,reserved 0sWie Sie sehen, hat der DRA-Treiber für alle Pods den Status „Ausstehend“ geändert.
allocated,reserved -
Laufen Sie
nvidia-smivom Knoten aus. Sie werden feststellen, dass drei Python-Prozessoren laufen:root@ip-100-64-173-145 bin]# nvidia-smi +-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 570.158.01 Driver Version: 570.158.01 CUDA Version: 12.8 | |-----------------------------------------+------------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |=========================================+========================+======================| | 0 NVIDIA A100-SXM4-80GB On | 00000000:10:1C.0 Off | On | | N/A 63C P0 127W / 400W | 569MiB / 81920MiB | N/A Default | | | | Enabled | +-----------------------------------------+------------------------+----------------------+ | 1 NVIDIA A100-SXM4-80GB On | 00000000:10:1D.0 Off | On | | N/A 56C P0 121W / 400W | 374MiB / 81920MiB | N/A Default | | | | Enabled | +-----------------------------------------+------------------------+----------------------+ | 2 NVIDIA A100-SXM4-80GB On | 00000000:20:1C.0 Off | On | | N/A 63C P0 128W / 400W | 467MiB / 81920MiB | N/A Default | | | | Enabled | +-----------------------------------------+------------------------+----------------------+ | 3 NVIDIA A100-SXM4-80GB On | 00000000:20:1D.0 Off | On | | N/A 57C P0 118W / 400W | 249MiB / 81920MiB | N/A Default | | | | Enabled | +-----------------------------------------+------------------------+----------------------+ | 4 NVIDIA A100-SXM4-80GB On | 00000000:90:1C.0 Off | 0 | | N/A 51C P0 77W / 400W | 0MiB / 81920MiB | 0% Default | | | | Disabled | +-----------------------------------------+------------------------+----------------------+ | 5 NVIDIA A100-SXM4-80GB On | 00000000:90:1D.0 Off | 0 | | N/A 46C P0 69W / 400W | 0MiB / 81920MiB | 0% Default | | | | Disabled | +-----------------------------------------+------------------------+----------------------+ | 6 NVIDIA A100-SXM4-80GB On | 00000000:A0:1C.0 Off | 0 | | N/A 52C P0 74W / 400W | 0MiB / 81920MiB | 0% Default | | | | Disabled | +-----------------------------------------+------------------------+----------------------+ | 7 NVIDIA A100-SXM4-80GB On | 00000000:A0:1D.0 Off | 0 | | N/A 47C P0 72W / 400W | 0MiB / 81920MiB | 0% Default | | | | Disabled | +-----------------------------------------+------------------------+----------------------+ +-----------------------------------------------------------------------------------------+ | MIG devices: | +------------------+----------------------------------+-----------+-----------------------+ | GPU GI CI MIG | Memory-Usage | Vol| Shared | | ID ID Dev | BAR1-Usage | SM Unc| CE ENC DEC OFA JPG | | | | ECC| | |==================+==================================+===========+=======================| | 0 2 0 0 | 428MiB / 40192MiB | 42 0 | 3 0 2 0 0 | | | 2MiB / 32767MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 0 3 0 1 | 71MiB / 19968MiB | 28 0 | 2 0 1 0 0 | | | 0MiB / 16383MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 0 9 0 2 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 0MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 0 10 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 0MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 1 1 0 0 | 107MiB / 40192MiB | 42 0 | 3 0 2 0 0 | | | 0MiB / 32767MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 1 5 0 1 | 71MiB / 19968MiB | 28 0 | 2 0 1 0 0 | | | 0MiB / 16383MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 1 13 0 2 | 161MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 2MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 1 14 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 0MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 2 1 0 0 | 107MiB / 40192MiB | 42 0 | 3 0 2 0 0 | | | 0MiB / 32767MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 2 5 0 1 | 289MiB / 19968MiB | 28 0 | 2 0 1 0 0 | | | 2MiB / 16383MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 2 13 0 2 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 0MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 2 14 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 0MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 3 1 0 0 | 107MiB / 40192MiB | 42 0 | 3 0 2 0 0 | | | 0MiB / 32767MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 3 5 0 1 | 71MiB / 19968MiB | 28 0 | 2 0 1 0 0 | | | 0MiB / 16383MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 3 13 0 2 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 0MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ | 3 14 0 3 | 36MiB / 9728MiB | 14 0 | 1 0 0 0 0 | | | 0MiB / 8191MiB | | | +------------------+----------------------------------+-----------+-----------------------+ +-----------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=========================================================================================| **| 0 2 0 64080 C python 312MiB | | 1 13 0 64085 C python 118MiB | | 2 5 0 64073 C python 210MiB |** +-----------------------------------------------------------------------------------------+
Optimieren Sie GPU-Workloads mit IMEX mithilfe von GB200 P6e-Instances
IMEX (Internode Memory Exchange) ermöglicht die speicherkohärente Kommunikation zwischen Knoten für verteiltes Training auf NVIDIA GB200. UltraServers
Führen Sie die folgenden Schritte aus.
-
Definieren Sie eine
ComputeDomainfür Training mit mehreren Knoten mit einer Datei namensimex-compute-domain.yaml:apiVersion: resource.nvidia.com/v1beta1 kind: ComputeDomain metadata: name: distributed-training-domain namespace: default spec: numNodes: 2 channel: resourceClaimTemplate: name: imex-channel-template -
Definieren Sie einen Pod mithilfe von IMEX-Kanälen mit einer Datei mit dem Namen:
imex-pod.yamlapiVersion: v1 kind: Pod metadata: name: imex-distributed-training namespace: default labels: app: imex-training spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: nvidia.com/gpu.clique operator: Exists containers: - name: distributed-training image: nvcr.io/nvidia/pytorch:25.04-py3 command: ["bash", "-c"] args: - | echo "=== IMEX Channel Verification ===" ls -la /dev/nvidia-caps-imex-channels/ echo "" echo "=== GPU Information ===" nvidia-smi echo "" echo "=== NCCL Test (if available) ===" python -c " import torch import torch.distributed as dist import os print(f'CUDA available: {torch.cuda.is_available()}') print(f'CUDA device count: {torch.cuda.device_count()}') if torch.cuda.is_available(): for i in range(torch.cuda.device_count()): print(f'GPU {i}: {torch.cuda.get_device_name(i)}') # Check for IMEX environment variables imex_vars = [k for k in os.environ.keys() if 'IMEX' in k or 'NVLINK' in k] if imex_vars: print('IMEX Environment Variables:') for var in imex_vars: print(f' {var}={os.environ[var]}') print('IMEX channel verification completed') " # Keep container running for inspection sleep 3600 resources: claims: - name: imex-channel-0 - name: imex-channel-1 resourceClaims: - name: imex-channel-0 resourceClaimTemplateName: imex-channel-template - name: imex-channel-1 resourceClaimTemplateName: imex-channel-template tolerations: - key: nvidia.com/gpu operator: Exists effect: NoScheduleAnmerkung
Dies erfordert P6e GB200-Instances.
-
Stellen Sie IMEX bereit, indem Sie die Vorlagen und anwenden:
ComputeDomainkubectl apply -f imex-claim-template.yaml kubectl apply -f imex-compute-domain.yaml kubectl apply -f imex-pod.yaml -
Überprüfen Sie den
ComputeDomainStatus.kubectl get computedomain distributed-training-domain -
Überwachen Sie die Bereitstellung des IMEX-Daemons.
kubectl get pods -n nvidia-dra-driver -l resource.nvidia.com/computeDomain -
Überprüfe die IMEX-Kanäle im Pod:
kubectl exec imex-distributed-training -- ls -la /dev/nvidia-caps-imex-channels/ -
Sehen Sie sich die Pod-Logs an:
kubectl logs imex-distributed-trainingDas Folgende ist ein Beispiel für die erwartete Ausgabe:
=== IMEX Channel Verification === total 0 drwxr-xr-x. 2 root root 80 Jul 8 10:45 . drwxr-xr-x. 6 root root 380 Jul 8 10:45 .. crw-rw-rw-. 1 root root 241, 0 Jul 8 10:45 channel0 crw-rw-rw-. 1 root root 241, 1 Jul 8 10:45 channel1
Weitere Informationen finden Sie im NVIDIA-Beispiel