Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.
Calcolo e scalabilità automatica
Ottimizzazione delle risorse GPU e gestione dei costi
Pianifica i carichi di lavoro con i requisiti della GPU utilizzando etichette Known
Per i AI/ML carichi di lavoro sensibili alle diverse caratteristiche della GPU (ad esempio GPU, memoria GPU), consigliamo di specificare i requisiti della GPU utilizzando etichette di pianificazione note supportate dai tipi di nodi utilizzati con Karpenter
Esempio
Ad esempio, utilizzando il selettore di nodi di nomi GPU quando si utilizza Karpenter:
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
Usa Kubernetes Device Plugin per esporre GPUs
Per eseguire l'esposizione GPUs sui nodi, il driver GPU NVIDIA deve essere installato sul sistema operativo del nodo e il runtime del contenitore deve essere configurato per consentire allo scheduler Kubernetes di assegnare i pod ai nodi se disponibili. GPUs Il processo di configurazione per il plugin per dispositivi NVIDIA Kubernetes dipende dall'AMI EKS Accelerated che stai utilizzando:
-
AMI Bottlerocket Accelerated: questa AMI include il driver GPU NVIDIA e il NVIDIA Kubernetes Device
Plugin è preinstallato e pronto all'uso, abilitando il supporto GPU immediatamente. Non è richiesta alcuna configurazione aggiuntiva per l'esposizione allo scheduler Kubernetes. GPUs -
AL2AMI accelerata 023: questa AMI
include il driver GPU NVIDIA, ma il plugin per dispositivi NVIDIA Kubernetes non è preinstallato. È necessario installare e configurare il plug-in del dispositivo separatamente, in genere tramite un. DaemonSet Nota che se usi eksctl per creare il tuo cluster e specifichi un tipo di istanza GPU (ad esempio g5.xlarge
) nel tuo ClusterConfig,eksctl
selezionerà automaticamente l'AMI accelerata e installerà il NVIDIA Kubernetes Device Plugin su ogni istanza del gruppo di nodi. Per saperne di più, consulta il supporto GPU nella documentazione di eksctl.
Per verificare che i NVIDIA Device Plugin siano attivi e GPUs siano esposti correttamente, esegui:
kubectl describe node | grep nvidia.com/gpu
Questo comando verifica se la nvidia.com/gpu
risorsa rientra nella capacità del nodo e nelle risorse allocabili. Ad esempio, dovrebbe essere visualizzato un nodo con una GPU. nvidia.com/gpu: 1
Per ulteriori informazioni, consulta la Kubernetes GPU Scheduling
Usa ML Capacity Blocks per garantire la capacità delle istanze P e Trainium
I Capacity Blocks for ML ti consentono di prenotare istanze GPU molto richieste, in particolare istanze P (ad esempio, p6-b200, p5, p5e, p5en, p4d, p4de) e istanze Trainium (ad es. trn1, trn2), da avviare quasi immediatamente o in date future per supportare i carichi di lavoro di machine learning (ML) di breve durata. Queste prenotazioni sono ideali per garantire la capacità necessaria per attività ad alta intensità di calcolo come la formazione dei modelli e la messa a punto. EC2 I prezzi di Capacity Blocks sono costituiti da una commissione di prenotazione e da una commissione per il sistema operativo. Per ulteriori informazioni sui prezzi, consulta i prezzi EC2 di Capacity Blocks for ML
GPUs Per riservare i AI/ML carichi di lavoro su Amazon EKS per una garanzia di capacità prevedibile, consigliamo di utilizzare i blocchi di capacità ML per le prenotazioni di capacità a breve termine o le prenotazioni di capacità su richiesta (ODCRs) per la garanzia della capacità generica.
-
ODCRs consentono di riservare la capacità delle EC2 istanze (ad esempio, istanze GPU come g5 o p5) in una zona di disponibilità specifica per una determinata durata, garantendo la disponibilità anche in caso di forte domanda. ODCRs non avete alcun impegno a lungo termine, ma pagate la tariffa On-Demand per la capacità riservata, utilizzata o inattiva. In EKS, ODCRs sono supportati da tipi di nodi come Karpenter
e gruppi di nodi gestiti. Per stabilire le priorità ODCRs in Karpenter, configura l'utilizzo del campo. NodeClass capacityReservationSelectorTerms
Vedi la documentazione di Karpenter. NodePools -
I Capacity Blocks sono un meccanismo di prenotazione specializzato per istanze GPU (ad esempio p5, p4d) o Trainium (trn1, trn2), progettato per carichi di lavoro ML a breve termine come la formazione di modelli, la messa a punto o la sperimentazione. Riservi la capacità per un periodo definito (in genere da 24 ore a 182 giorni) a partire da una data futura, pagando solo per il tempo prenotato. Sono prepagate, richiedono una pianificazione preliminare in base alle esigenze di capacità e non supportano la scalabilità automatica, ma sono collocate in modo isolato per reti a bassa latenza. EC2 UltraClusters Fanno pagare solo per il periodo prenotato. Per saperne di più, consulta Trova e acquista blocchi di capacità oppure inizia a configurare gruppi di nodi gestiti con Capacity Blocks seguendo le istruzioni contenute in Creare un gruppo di nodi gestiti con blocchi di capacità per ML.
Riserva la capacità tramite la Console di gestione AWS e configura i nodi per utilizzare blocchi di capacità ML. Pianifica le prenotazioni in base alla pianificazione dei carichi di lavoro ed esegui i test in un cluster di staging. Per ulteriori informazioni, consulta la documentazione relativa ai blocchi di capacità.
Prendi in considerazione On-Demand, Amazon EC2 Spot o On-Demand Capacity Reservations (ODCRs) per le istanze G Amazon EC2
Per EC2 le istanze Amazon G, considera le diverse opzioni di acquisto tra On-Demand, Amazon EC2 Spot Instances e On-Demand Capacity Reservations. ODCRsconsentono di riservare la capacità delle EC2 istanze in una zona di disponibilità specifica per un determinato periodo, garantendo la disponibilità anche in caso di forte domanda. A differenza delle istanze ML Capacity, disponibili solo per le istanze P e Trainium, ODCRs possono essere utilizzati per una gamma più ampia di tipi di istanze, comprese le istanze G, il che li rende adatti a carichi di lavoro che richiedono funzionalità GPU diverse, come l'inferenza o la grafica. Quando si utilizzano le istanze Amazon EC2 Spot, la possibilità di diversificare tra diversi tipi, dimensioni e zone di disponibilità è fondamentale per poter rimanere su Spot più a lungo.
ODCRs non avete alcun impegno a lungo termine, ma pagate la tariffa On-Demand per la capacità riservata, utilizzata o inattiva. ODCRs possono essere creati per un uso immediato o programmati per date future, garantendo flessibilità nella pianificazione della capacità. In Amazon EKS, ODCRs sono supportati da tipi di nodi come Karpenter e gruppicapacityReservationSelectorTerms
Vedi la documentazione di Karpenter. NodePools
Prendi in considerazione altri tipi e dimensioni di istanze accelerate
La selezione dell'istanza accelerata e della dimensione appropriate è essenziale per ottimizzare prestazioni e costi nei carichi di lavoro ML su Amazon EKS. Ad esempio, diverse famiglie di istanze GPU hanno prestazioni e funzionalità diverse, come la memoria GPU. Per aiutarti a scegliere l'opzione con il miglior rapporto prezzo/prestazioni, consulta le istanze GPU disponibili nella pagina Tipi di istanze in Accelerated Computing. EC2
Se si utilizza un'istanza GPU in un nodo EKS, per impostazione predefinita il nvidia-device-plugin-daemonset
pod verrà inserito nel kube-system
namespace. Per capire rapidamente se state utilizzando appieno le GPU della vostra istanza, potete usare nvidia-smi come mostrato di seguito:
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
-
Se
utilization.memory
è vicino al 100%, è probabile che i tuoi codici siano vincolati alla memoria. Ciò significa che la GPU (memoria) è completamente utilizzata, ma potrebbe suggerire che sia necessario studiare un'ulteriore ottimizzazione delle prestazioni. -
Se
utilization.gpu
è vicino al 100%, ciò non significa necessariamente che la GPU sia completamente utilizzata. Una metrica migliore da considerare è il rapporto tra a.power.draw
power.limit
Se questo rapporto è pari o superiore al 100%, i tuoi codici stanno utilizzando appieno la capacità di calcolo della GPU. -
Il
-l 5
flag indica di emettere le metriche ogni 5 secondi. Nel caso di un singolo tipo di istanza GPU, il flag di interrogazione dell'indice non è necessario.
Per ulteriori informazioni, consulta le istanze GPU nella documentazione di AWS.
Ottimizza l'allocazione delle risorse GPU con Time-Slicing, MIG e l'allocazione frazionata della GPU
I limiti statici delle risorse in Kubernetes (ad esempio, CPU, memoria, numero di GPU) possono portare a un approvvigionamento eccessivo o al sottoutilizzo, in particolare per carichi di lavoro dinamici come l'inferenza. AI/ML La scelta della GPU giusta è importante. Per carichi di lavoro a basso volume o con picchi di traffico, il time-slicing consente a più carichi di lavoro di condividere una singola GPU condividendone le risorse di elaborazione, migliorando potenzialmente l'efficienza e riducendo gli sprechi. La condivisione della GPU può essere ottenuta tramite diverse opzioni:
-
Sfrutta i selettori dei nodi e l'affinità dei nodi per influenzare la pianificazione: assicurati che i nodi forniti e i pod siano pianificati in modo appropriato GPUs per il carico di lavoro (ad esempio,)
karpenter.k8s.aws/instance-gpu-name: "a100"
-
Time-Slicing: pianifica i carichi di lavoro per condividere le risorse di calcolo di una GPU nel tempo, permettendo l'esecuzione simultanea senza partizionamento fisico. È ideale per carichi di lavoro con esigenze di elaborazione variabili, ma può mancare l'isolamento della memoria.
-
GPU multiistanza (MIG): MIG consente di partizionare una singola GPU NVIDIA in più istanze isolate ed è supportata con NVIDIA Ampere (ad esempio, GPU A100), NVIDIA Hopper (ad esempio, GPU H100) e NVIDIA Blackwell (ad esempio Blackwell). GPUs GPUs Ogni istanza MIG riceve risorse di calcolo e memoria dedicate, che consentono la condivisione delle risorse in ambienti multi-tenant o carichi di lavoro che richiedono garanzie di risorse, il che consente di ottimizzare l'utilizzo delle risorse GPU, inclusi scenari come la gestione di più modelli con batch di diverse dimensioni tramite time-slicing.
-
Allocazione frazionata della GPU: utilizza la pianificazione basata su software per allocare parti del calcolo o della memoria di una GPU ai carichi di lavoro, offrendo flessibilità per carichi di lavoro dinamici. NVIDIA KAI Scheduler, parte della piattaforma Run:AI
, consente tutto ciò consentendo ai pod di richiedere risorse GPU frazionarie.
Per abilitare queste funzionalità in EKS, puoi implementare il NVIDIA Device Plugin, che utilizza come risorse programmabili e supporta time-slicing e MIG. GPUs Per saperne di più, consulta Time-Slicing GPUs in Kubernetes e condivisione della GPU su Amazon EKS con
Esempio
Ad esempio, per abilitare il time-slicing con il plugin per dispositivi NVIDIA:
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
Esempio
Ad esempio, per utilizzare KAI Scheduler per l'allocazione frazionata della GPU, implementalo insieme a NVIDIA GPU Operator e specifica le risorse GPU frazionarie nelle specifiche del pod:
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
Resilienza dei nodi e gestione dei lavori di formazione
Implementa Node Health Checks con il ripristino automatico
Per i lavori di formazione distribuiti su Amazon EKS che richiedono comunicazioni frequenti tra nodi, come l'addestramento su modelli multi-GPU su più nodi, problemi hardware come guasti della GPU o dell'EFA possono causare interruzioni dei lavori di formazione. Queste interruzioni possono portare alla perdita di progressi nella formazione e all'aumento dei costi, in particolare per carichi di lavoro di lunga durata che si basano su hardware stabile. AI/ML
Per aumentare la resilienza contro i guasti hardware, come i guasti della GPU nei cluster EKS che eseguono carichi di lavoro GPU, consigliamo di utilizzare EKS Node Monitoring Agent con Auto Repair o Amazon. SageMaker HyperPod Mentre EKS Node Monitoring Agent with Auto Repair offre funzionalità come il monitoraggio dello stato dei nodi e la riparazione automatica utilizzando meccanismi Kubernetes standard, SageMaker HyperPod offre resilienza mirata e funzionalità aggiuntive progettate specificamente per la formazione ML su larga scala, come controlli approfonditi dello stato e ripresa automatica dei lavori.
-
L'EKS Node Monitoring Agent con Node Auto Repair monitora continuamente lo stato dei nodi leggendo i log
Ready
e applicando NodeConditions, incluse condizioni standard come quelle specifiche dell'hardware accelerato per identificare problemi come guasti della GPU o della rete. Quando un nodo è considerato non integro, Node Auto Repair lo isola e lo sostituisce con un nuovo nodo. La riprogrammazione dei pod e il riavvio dei lavori si basano sui meccanismi standard di Kubernetes e sulla politica di riavvio del processo. -
L'agente per i controlli SageMaker HyperPod
approfonditi e il monitoraggio dello stato di salute monitora continuamente lo stato di salute delle istanze basate su GPU e Trainium. È personalizzato per i AI/ML carichi di lavoro e utilizza etichette (ad esempio) per gestire lo stato dei nodi. node-health-status Quando un nodo è considerato non integro, HyperPod attiva la sostituzione automatica dell'hardware difettoso, ad esempio. GPUs Per impostazione predefinita, rileva i guasti relativi alla rete per l'EFA attraverso i suoi controlli sanitari di base e supporta la ripresa automatica dei lavori di formazione interrotti, consentendo di continuare i lavori dall'ultimo checkpoint e riducendo al minimo le interruzioni per le attività di machine learning su larga scala.
Sia per EKS Node Monitoring Agent con Auto Repair che per SageMaker HyperPod i cluster che utilizzano EFA, per monitorare metriche specifiche di EFA come errori di Remote Direct Memory Access (RDMA) e cadute di pacchetti, assicurati che il driver AWS EFA sia installato. Inoltre, consigliamo di implementare l'CloudWatch Observability Add-on o di utilizzare strumenti come DCGM Exporter con Prometheus e Grafana per monitorare EFA, GPU e, per esempio, metriche specifiche relative alle sue funzionalità. SageMaker HyperPod
Disabilita Karpenter Consolidation per carichi di lavoro sensibili alle interruzioni
Per i carichi di lavoro sensibili alle interruzioni, come l'elaborazione, le attività di AI/ML previsione su larga scala o la formazione, consigliamo di ottimizzare le politiche di consolidamento di Karpenter per evitare interruzioni durante l'esecuzione del lavoro.
La politica di WhenEmptyOrUnderutilized
consolidamento può chiudere i nodi prematuramente, con conseguenti tempi di esecuzione più lunghi. Ad esempio, le interruzioni possono ritardare la ripresa dei job a causa della riprogrammazione dei pod e del ricaricamento dei dati, il che potrebbe essere costoso per i lavori di inferenza in batch di lunga durata. Per ovviare a questo problema, puoi impostare WhenEmpty
e configurare una consolidateAfter
durata, ad esempio 1 ora, consolidationPolicy
per conservare i nodi durante i picchi di carico di lavoro. Per esempio:
disruption: consolidationPolicy: WhenEmpty consolidateAfter: 60m
Questo approccio migliora la latenza di avvio dei pod per carichi di lavoro di inferenza in batch complessi e altri lavori sensibili alle interruzioni, come l'elaborazione di dati di inferenza online in tempo reale o l'addestramento dei modelli, in cui il costo dell'interruzione supera i risparmi sui costi di elaborazione. NodePool Karpenter
Usa ttlSecondsAfter Finished per la pulizia automatica dei lavori Kubernetes
Consigliamo di impostare ttlSecondsAfterFinished
i job Kubernetes in Amazon EKS per eliminare automaticamente gli oggetti di lavoro completati. Gli oggetti di lavoro persistenti consumano risorse del cluster, come la memoria del server API, e complicano il monitoraggio con dashboard ingombranti (ad esempio Grafana, Amazon). CloudWatch Ad esempio, l'impostazione di un TTL di 1 ora garantisce che i lavori vengano rimossi subito dopo il completamento, mantenendo il cluster in ordine. Per ulteriori dettagli, consulta Pulizia automatica per lavori finiti.
Configurazione della priorità dei lavori a bassa priorità per lavori/carichi di lavoro con priorità più alta
Per i carichi di AI/ML lavoro a priorità mista su Amazon EKS, puoi configurare la priorità dei lavori a bassa priorità per garantire che le attività con priorità più alta (ad esempio, inferenza in tempo reale) ricevano risorse tempestivamente. Senza prelazione, i carichi di lavoro a bassa priorità come i processi batch (ad es. inferenza in batch, elaborazione dei dati), i servizi non batch (ad esempio, attività in background, cron job) o i lavori che richiedono un uso intensivo di CPU/memoria (ad esempio i servizi Web) possono ritardare i pod critici occupando i nodi. La priorità consente a Kubernetes di eliminare i pod a bassa priorità quando i pod ad alta priorità richiedono risorse, garantendo un'allocazione efficiente delle risorse sui nodi con GPUs o memoria. CPUs Ti consigliamo di utilizzare Kubernetes per assegnare priorità e controllare il comportamento di sfratto. PriorityClass
PodDisruptionBudget
apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: low-priority value: 100 --- spec: priorityClassName: low-priority
Per ulteriori informazioni, consulta la documentazione sulla priorità e la priorità di Kubernetes
Scalabilità e prestazioni delle applicazioni
Personalizza la capacità di calcolo per i carichi di lavoro ML con Karpenter o Static Nodes
Per garantire una capacità di calcolo efficiente in termini di costi e reattiva per i flussi di lavoro di machine learning (ML) su Amazon EKS, consigliamo di personalizzare la strategia di provisioning dei nodi in base alle caratteristiche del carico di lavoro e agli impegni di costo. Di seguito sono riportati due approcci da considerare: just-in-time scalabilità con Karpenter e gruppi di nodi statici per la capacità riservata.
-
Just-in-time scaler sul piano di dati come Karpenter: per flussi di lavoro ML dinamici con richieste di calcolo variabili (ad esempio, inferenza basata su GPU seguita da grafici basati su CPU), consigliamo di utilizzare scalatori sul piano dati come Karpenter. just-in-time
-
Utilizza gruppi di nodi statici per carichi di lavoro prevedibili: per carichi di lavoro ML prevedibili e stazionari o quando si utilizzano istanze riservate, i gruppi di nodi gestiti da EKS possono contribuire a garantire che la capacità riservata sia completamente fornita e utilizzata, massimizzando i risparmi. Questo approccio è ideale per tipi di istanze specifici eseguiti tramite o. RIs ODCRs
Esempio
Questo è un esempio di Karpenter diversificato NodePoolg
Amazon in cui la generazione di EC2 istanze è superiore a tre.
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
Esempio
Esempio di utilizzo di gruppi di nodi statici per un carico di lavoro di formazione:
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
Utilizza fattori e tolleranze per impedire che carichi di lavoro non accelerati vengano pianificati su istanze accelerate
La pianificazione di carichi di lavoro non accelerati su risorse GPU non è efficiente dal punto di vista del calcolo, pertanto consigliamo di utilizzare taints and toleration per garantire che i pod di carichi di lavoro non accelerati non siano pianificati su nodi inappropriati. Per ulteriori informazioni
Scalabilità basata sulle prestazioni del modello
Per i carichi di lavoro di inferenza, consigliamo di utilizzare Kubernetes Event-Driven Autoscaling (KEDA) per scalare in base a metriche prestazionali del modello come le richieste di inferenza o il throughput dei token, con periodi di cooldown appropriati. Le politiche di scalabilità statica possono sovrafornire o sottodimensionare le risorse, con un impatto sui costi e sulla latenza. Scopri di più nella documentazione KEDA.
Allocazione dinamica delle risorse per la gestione avanzata delle GPU
L'allocazione dinamica delle risorse (DRA)
-
Allocazione di GPU a grana fine
-
Meccanismi di condivisione avanzati, come Multi-Process Service (MPS) e Multi-Instance GPU (MIG)
-
Support per architetture hardware di nuova generazione, tra cui NVIDIA 00 GB2 UltraClusters
L'allocazione tradizionale delle GPU viene considerata GPUs come risorse intere opache, con conseguente sottoutilizzo significativo (spesso del 30-40% nei cluster di produzione). Ciò si verifica perché i carichi di lavoro ricevono l'accesso esclusivo all'intero anche quando richiedono solo risorse frazionarie. GPUs DRA trasforma questo modello introducendo un'allocazione strutturata e dichiarativa che fornisce allo scheduler Kubernetes una visibilità completa sulle caratteristiche hardware e sui requisiti del carico di lavoro. Ciò consente decisioni di posizionamento intelligenti e una condivisione efficiente delle risorse.
Vantaggi dell'utilizzo di DRA anziché del plug-in per dispositivi NVIDIA
Il plug-in per dispositivi NVIDIA (a partire dalla versione0.12.0
) supporta meccanismi di condivisione della GPU tra cui time-slicing, MPS e MIG. Tuttavia, esistono limitazioni architettoniche che DRA affronta.
Limitazioni dei plug-in per dispositivi NVIDIA
-
Configurazione statica: le configurazioni di condivisione della GPU (repliche time-slicing e impostazioni MPS) richiedono la preconfigurazione a livello di cluster.
ConfigMaps
Ciò rende difficile fornire strategie di condivisione diverse per carichi di lavoro diversi. -
Selezione granulare limitata: sebbene il plug-in del dispositivo esponga le caratteristiche della GPU tramite le etichette dei nodi, i carichi di lavoro non possono richiedere dinamicamente configurazioni GPU specifiche (dimensioni della memoria e capacità di calcolo) come parte della decisione di pianificazione.
-
Nessun coordinamento delle risorse tra nodi: non è possibile gestire risorse GPU distribuite su più nodi o esprimere requisiti topologici complessi come i domini per sistemi come NVIDIA 00. NVLink GB2
-
Vincoli dello scheduler: lo scheduler Kubernetes tratta le risorse GPU come numeri interi opachi, limitando la sua capacità di prendere decisioni basate sulla topologia o di gestire dipendenze complesse dalle risorse.
-
Complessità di configurazione: l'impostazione di diverse strategie di condivisione richiede un'etichettatura multipla e attenta dei nodi, creando complessità operativa.
ConfigMaps
Soluzioni con DRA
-
Selezione dinamica delle risorse: DRA consente ai carichi di lavoro di specificare requisiti dettagliati (memoria GPU, versioni dei driver e attributi specifici) al momento della richiesta.
resourceclaims
Ciò consente una corrispondenza più flessibile delle risorse. -
Conoscenza della topologia: tramite parametri strutturati e selettori di dispositivi, DRA gestisce requisiti complessi come la comunicazione GPU tra nodi e le interconnessioni coerenti con la memoria.
-
Gestione delle risorse tra nodi:
computeDomains
abilita il coordinamento delle risorse GPU distribuite su più nodi, fondamentale per sistemi come 00 con canali IMEX. GB2 -
Configurazione specifica per il carico di lavoro: ciascuna
ResourceClaim
specifica strategie e configurazioni di condivisione diverse, consentendo un controllo granulare per carico di lavoro anziché impostazioni a livello di cluster. -
Integrazione migliorata dello scheduler: DRA fornisce allo scheduler informazioni dettagliate sul dispositivo e consente decisioni di posizionamento più intelligenti in base alla topologia hardware e alle caratteristiche delle risorse.
Importante: DRA non sostituisce completamente il plug-in del dispositivo NVIDIA. Il driver NVIDIA DRA funziona insieme al plug-in del dispositivo per fornire funzionalità avanzate. Il plug-in del dispositivo continua a gestire l'individuazione e la gestione di base della GPU, mentre DRA aggiunge funzionalità avanzate di allocazione e pianificazione.
Istanze supportate da DRA e relative funzionalità
Il supporto DRA varia in base alla famiglia di EC2 istanze Amazon e all'architettura GPU, come illustrato nella tabella seguente.
Famiglia di istanze | Tipo di GPU | Separazione temporale | Supporto MIG | Supporto MPS | Supporto IMEX | Casi d'uso |
---|---|---|---|---|---|---|
G5 |
NVIDIA A10G |
Sì |
No |
Sì |
No |
Carichi di lavoro di inferenza e grafica |
G6 |
NVIDIA L4 |
Sì |
No |
Sì |
No |
Inferenza AI ed elaborazione video |
G6e |
NVIDIA L40S |
Sì |
No |
Sì |
No |
Formazione, inferenza e grafica |
P4D/P4DE |
NVIDIA A100 |
Sì |
Sì |
Sì |
No |
Formazione su larga scala e HPC |
P5 |
NVIDIA H100 |
Sì |
Sì |
Sì |
No |
Formazione sul modello Foundation |
P6 |
NVIDIA B200 |
Sì |
Sì |
Sì |
No |
Modelli con miliardi o trilioni di parametri, addestramento distribuito e inferenza |
P6e |
NVIDIA 00 GB2 |
Sì |
Sì |
Sì |
Sì |
Modelli con miliardi o trilioni di parametri, addestramento distribuito e inferenza |
Di seguito sono riportate le descrizioni di ciascuna funzionalità della tabella:
-
Time-slicing: consente a più carichi di lavoro di condividere le risorse di calcolo della GPU nel tempo.
-
GPU multiistanza (MIG): partizionamento a livello hardware che crea istanze GPU isolate.
-
Servizio multiprocesso (MPS): consente l'esecuzione simultanea di più processi CUDA su una singola GPU.
-
Internode Memory Exchange (IMEX): comunicazione coerente in termini di memoria tra i nodi per 00. GB2 UltraClusters
Risorse aggiuntive
Per ulteriori informazioni sui driver Kubernetes DRA e NVIDIA DRA, consulta le seguenti risorse su: GitHub
Configura l'allocazione dinamica delle risorse per la gestione avanzata delle GPU
L'argomento seguente mostra come configurare l'allocazione dinamica delle risorse (DRA) per la gestione avanzata delle GPU.
Prerequisiti
Prima di implementare DRA su Amazon EKS, assicurati che il tuo ambiente soddisfi i seguenti requisiti.
Configurazione del cluster
-
Cluster Amazon EKS in esecuzione
1.33
o versione successiva -
Nodi di lavoro compatibili con GPU NVIDIA con tipi di istanze appropriati
Componenti richiesti
-
Versione del plug-in per dispositivi NVIDIA
0.17.1
o successiva -
Versione del driver NVIDIA DRA o successiva
25.3.0
Fase 1: Creare un cluster con un gruppo di nodi abilitato al DRA utilizzando eksctl
-
Crea un file di configurazione del cluster denominato:
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
-
Crea il cluster:
eksctl create cluster -f dra-eks-cluster.yaml
Fase 2: Implementazione del plug-in per dispositivi NVIDIA
Implementa il plug-in per dispositivi NVIDIA per abilitare l'individuazione di base della GPU:
-
Aggiungi il repository Helm del plug-in per dispositivi NVIDIA:
helm repo add nvidia https://nvidia.github.io/k8s-device-plugin helm repo update
-
Crea valori personalizzati per il plug-in del dispositivo:
cat <<EOF > nvidia-device-plugin-values.yaml gfd: enabled: true nfd: enabled: true tolerations: - key: [nvidia.com/gpu](http://nvidia.com/gpu) operator: Exists effect: NoSchedule EOF
-
Installa il plug-in del dispositivo NVIDIA:
helm install nvidia-device-plugin nvidia/nvidia-device-plugin \ --namespace nvidia-device-plugin \ --create-namespace \ --version v0.17.1 \ --values nvidia-device-plugin-values.yaml
Fase 3: Implementazione del driver NVIDIA DRA Helm chart
-
Crea un file di
dra-driver-values.yaml
valori per il driver DRA:--- 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
-
Aggiungi il repository NVIDIA NGC Helm:
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia helm repo update
-
Installa il driver NVIDIA DRA:
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
Fase 4: Verificare l'installazione del DRA
-
Verificate che le risorse dell'API DRA siano disponibili:
kubectl api-resources | grep [resource.k8s.io/v1beta1](http://resource.k8s.io/v1beta1)
Di seguito è riportato l'output previsto:
deviceclasses [resource.k8s.io/v1beta1](http://resource.k8s.io/v1beta1) false DeviceClass resourceclaims [resource.k8s.io/v1beta1](http://resource.k8s.io/v1beta1) true ResourceClaim resourceclaimtemplates [resource.k8s.io/v1beta1](http://resource.k8s.io/v1beta1) true ResourceClaimTemplate resourceslices [resource.k8s.io/v1beta1](http://resource.k8s.io/v1beta1) false ResourceSlice
-
Controlla le classi di dispositivi disponibili:
kubectl get deviceclasses
Di seguito è riportato un esempio di output previsto:
NAME AGE compute-domain-daemon.nvidia.com 4h39m compute-domain-default-channel.nvidia.com 4h39m gpu.nvidia.com 4h39m mig.nvidia.com 4h39m
Quando un'istanza GPU G6 appena creata si unisce al cluster Amazon EKS con DRA abilitato, si verificano le seguenti azioni:
-
Il driver NVIDIA DRA rileva automaticamente la GPU A10G e ne crea due su quel nodo.
resourceslices
-
La
gpu.nvidia.com
slice registra il dispositivo GPU A10G fisico con le sue specifiche (memoria, capacità di elaborazione e altro). -
Poiché A10G non supporta il partizionamento MIG, la
compute-domain.nvidia.com
slice crea un singolo dominio di calcolo che rappresenta l'intero contesto di calcolo della GPU. -
Questi
resourceslices
vengono quindi pubblicati sul server API Kubernetes, rendendo le risorse della GPU disponibili per la pianificazione.resourceclaims
Lo scheduler DRA può ora allocare in modo intelligente questa GPU ai Pod che richiedono risorse GPU, fornendo una gestione delle risorse più flessibile rispetto agli approcci tradizionali basati sui plug-in dei dispositivi
resourceclaimtemplates
. Ciò avviene automaticamente senza intervento manuale. Il nodo diventa disponibile semplicemente per i carichi di lavoro della GPU una volta che il driver DRA ha completato il processo di individuazione e registrazione delle risorse.Quando si esegue il comando seguente:
kubectl get resourceslices
Di seguito è riportato un esempio di output previsto:
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
-
Continua su Pianifica un carico di lavoro GPU semplice utilizzando l'allocazione dinamica delle risorse.
Pianifica un carico di lavoro GPU semplice utilizzando l'allocazione dinamica delle risorse
Per pianificare un carico di lavoro GPU semplice utilizzando l'allocazione dinamica delle risorse (DRA), procedi nel seguente modo. Prima di procedere, assicurati di averlo seguito. Configura l'allocazione dinamica delle risorse per la gestione avanzata delle GPU
-
Crea una base
ResourceClaimTemplate
per l'allocazione della GPU con un file denominato:basic-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
-
Applica il modello:
kubectl apply -f basic-gpu-claim-template.yaml
-
Verifica lo stato:
kubectl get resourceclaimtemplates -n gpu-test1
Di seguito è riportato un output di esempio:
NAME AGE single-gpu 9m16s
-
Crea un Pod che usi il
ResourceClaimTemplate
con un file chiamatobasic-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"
-
Applica e monitora il Pod:
kubectl apply -f basic-gpu-pod.yaml
-
Controlla lo stato del Pod:
kubectl get pod -n gpu-test1
Di seguito è riportato un esempio di output previsto:
NAME READY STATUS RESTARTS AGE gpu-pod 1/1 Running 0 13m
-
Controlla lo
ResourceClaim
stato:kubectl get resourceclaims -n gpu-test1
Di seguito è riportato un esempio di output previsto:
NAME STATE AGE gpu-pod-gpu0-l76cg allocated,reserved 9m6s
-
Visualizza i log dei Pod per visualizzare le informazioni sulla GPU:
kubectl logs gpu-pod -n gpu-test1
Di seguito è riportato un esempio di output previsto:
GPU 0: NVIDIA L4 (UUID: GPU-da7c24d7-c7e3-ed3b-418c-bcecc32af7c5)
Continua a leggere Tecniche di ottimizzazione della GPU con allocazione dinamica delle risorse per tecniche di ottimizzazione della GPU più avanzate utilizzando DRA.
Tecniche di ottimizzazione della GPU con allocazione dinamica delle risorse
I carichi di lavoro GPU moderni richiedono una gestione sofisticata delle risorse per ottenere un utilizzo ottimale e un'efficienza dei costi. DRA consente diverse tecniche di ottimizzazione avanzate che rispondono a diversi casi d'uso e funzionalità hardware:
-
Il time-slicing consente a più carichi di lavoro di condividere le risorse di calcolo della GPU nel tempo, rendendolo ideale per carichi di lavoro di inferenza con utilizzo sporadico della GPU. Per vedere un esempio, consulta Ottimizza i carichi di lavoro della GPU con time-slicing.
-
Il servizio Multi-Process (MPS) consente l'esecuzione simultanea di più processi CUDA su una singola GPU con un isolamento migliore rispetto al time-slicing. Per vedere un esempio, consulta Ottimizza i carichi di lavoro della GPU con MPS.
-
La GPU multiistanza (MIG) fornisce il partizionamento a livello hardware, creando istanze GPU isolate con risorse di calcolo e memoria dedicate. Per vedere un esempio, consulta Ottimizza i carichi di lavoro della GPU con GPU multiistanza.
-
Internode Memory Exchange (IMEX) consente una comunicazione coerente in termini di memoria tra i nodi per la formazione distribuita sui sistemi NVIDIA 00. GB2 Per vedere un esempio, consulta Ottimizza i carichi di lavoro della GPU con IMEX utilizzando 100 istanze P6e GB2.
Queste tecniche possono migliorare significativamente l'utilizzo delle risorse. Le organizzazioni segnalano che l'utilizzo della GPU aumenta dal 30-40% con l'allocazione tradizionale all'80-90% con strategie di condivisione ottimizzate. La scelta della tecnica dipende dalle caratteristiche del carico di lavoro, dai requisiti di isolamento e dalle capacità hardware.
Ottimizza i carichi di lavoro della GPU con time-slicing
Il time-slicing consente a più carichi di lavoro di condividere le risorse di calcolo della GPU pianificandone l'esecuzione in sequenza sulla stessa GPU fisica. È ideale per carichi di lavoro di inferenza con utilizzo sporadico della GPU.
Effettuare le seguenti operazioni.
-
Definite un file
ResourceClaimTemplate
per il time-slicing con un file denominato: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
-
Definite un Pod usando il time-slicing con un file chiamato:
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
-
Applica il modello e il Pod:
kubectl apply -f timeslicing-claim-template.yaml kubectl apply -f timeslicing-pod.yaml
-
Monitora le richieste di risorse:
kubectl get resourceclaims -n timeslicing-gpu -w
Di seguito è riportato un output di esempio:
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
Primo Pod (inference-pod-1
)
-
Stato:
allocated,reserved
-
Significato: DRA ha trovato una GPU disponibile e l'ha riservata per questo Pod
-
Stato del pod: inizia a funzionare immediatamente
Secondo Pod (training-pod-2
)
-
Stato:
pending
-
Significato: in attesa che DRA configuri il time-slicing sulla stessa GPU
-
Stato del pod: In attesa di essere programmato
-
Lo stato passerà dal
pending
allocated,reserved
alrunning
Ottimizza i carichi di lavoro della GPU con MPS
Multi-Process Service (MPS) consente l'esecuzione simultanea di più contesti CUDA su una singola GPU con un isolamento migliore rispetto al time-slicing.
Effettuare le seguenti operazioni.
-
Definite un file
ResourceClaimTemplate
per MPS con il nomemps-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
-
Definite un Pod utilizzando MPS con un file denominato:
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
-
Applica il modello e crea più MPS Pod:
kubectl apply -f mps-claim-template.yaml kubectl apply -f mps-pod.yaml
-
Monitora le richieste di risorse:
kubectl get resourceclaims -n mps-gpu -w
Di seguito è riportato un output di esempio:
NAME STATE AGE mps-multi-container-pod-shared-gpu-claim-2p9kx allocated,reserved 86s
Questa configurazione dimostra una vera condivisione della GPU utilizzando NVIDIA Multi-Process Service (MPS) tramite l'allocazione dinamica delle risorse (DRA). A differenza del time-slicing, in cui i carichi di lavoro utilizzano a turno la GPU in sequenza, MPS consente l'esecuzione simultanea di entrambi i container sulla stessa GPU fisica. L'intuizione principale è che la condivisione di DRA MPS richiede più contenitori all'interno di un singolo Pod, non più Pod separati. Una volta distribuito, il driver DRA ne ResourceClaim
assegna uno al Pod e configura automaticamente MPS per consentire l'esecuzione simultanea dei contenitori di inferenza e di addestramento.
Ogni contenitore dispone del proprio spazio di memoria GPU e delle proprie risorse di calcolo isolate, con il daemon MPS che coordina l'accesso all'hardware sottostante. È possibile verificare che funzioni effettuando le seguenti operazioni:
-
Verifica
nvidia-smi
, che mostrerà entrambi i contenitori come processi M+C (MPS + Compute
) che condividono lo stesso dispositivo GPU. -
Monitoraggio dei log di entrambi i contenitori, che mostreranno timestamp interlacciati che dimostrano l'esecuzione simultanea.
Questo approccio massimizza l'utilizzo della GPU consentendo ai carichi di lavoro complementari di condividere in modo efficiente il costoso hardware della GPU, anziché lasciarlo sottoutilizzato da un singolo processo.
Contenitore 1: inference-container
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 |
+-----------------------------------------------------------------------------------------+
Contenitore 2: training-container
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 |
+-----------------------------------------------------------------------------------------+
Ottimizza i carichi di lavoro della GPU con GPU multiistanza
La GPU multiistanza (MIG) fornisce il partizionamento a livello hardware, creando istanze GPU isolate con risorse di calcolo e memoria dedicate.
L'utilizzo del partizionamento MIG dinamico con vari profili richiede l'operatore GPU NVIDIA.WITH0—REBOOT=true
nella configurazione MIG Manager è essenziale per implementazioni MIG di successo.
Sono necessari sia NVIDIA DRA Driver
Fase 1: Implementare NVIDIA GPU Operator
-
Aggiungi il repository NVIDIA GPU Operator:
helm repo add nvidia https://nvidia.github.io/gpu-operator helm repo update
-
Crea un file:
gpu-operator-values.yaml
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
-
Installa GPU Operator utilizzando il
gpu-operator-values.yaml
file:helm install gpu-operator nvidia/gpu-operator \ --namespace gpu-operator \ --create-namespace \ --version v25.3.1 \ --values gpu-operator-values.yaml
Questo grafico Helm utilizza i seguenti componenti e più profili MIG:
-
Device Plugin (pianificazione delle risorse GPU)
-
DCGM Exporter (metriche e monitoraggio della GPU)
-
Node Feature Discovery (NFD - etichettatura hardware)
-
GPU Feature Discovery (GFD - etichettatura specifica per GPU)
-
MIG Manager (partizionamento GPU multiistanza)
-
Container Toolkit (runtime del contenitore GPU)
-
Operator Controller (gestione del ciclo di vita)
-
-
Verifica i pod di distribuzione:
kubectl get pods -n gpu-operator
Di seguito è riportato un output di esempio:
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
-
Crea un cluster Amazon EKS con un gruppo di nodi gestiti P4de per testare gli esempi MIG:
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 ID
NVIDIA GPU Operator utilizza l'etichetta aggiunta ai nodi
nvidia.com/mig.config: "p4de-half-balanced"
e partiziona la GPU con il profilo specificato. -
Accedi all'istanza.
p4de
-
Esegui il comando seguente:
nvidia-smi -L
Dovresti vedere il seguente output di esempio:
[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 ha applicato con successo il profilo p4de-half-balanced
MIG all'istanza P4DE, creando partizioni GPU a livello hardware come configurato. Ecco come funziona il partizionamento:
L'operatore GPU ha applicato questa configurazione dal profilo MIG incorporato:
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
In base al tuo nvidia-smi -L
output, ecco cosa ha creato l'operatore GPU:
-
Compatibile con MIG GPUs (0-3): hardware partizionato
-
GPU 0: NVIDIA A100- 80 GB SXM4
-
MIG 3g.40gb Device 0 — Carichi di lavoro di grandi dimensioni (40 GB di memoria, 42) SMs
-
MIG 2g.20gb Device 1 — Carichi di lavoro medi (20 GB di memoria, 28) SMs
-
MIG 1g.10gb Device 2 — Piccoli carichi di lavoro (10 GB di memoria, 14) SMs
-
MIG 1g.10gb Device 3 — Piccoli carichi di lavoro (10 GB di memoria, 14) SMs
-
-
GPU 1: NVIDIA A100- -80 GB SXM4
-
MIG 3g.40gb Device 0 — Layout di partizione identico
-
MIG 2g.20gb Dispositivo 1
-
MIG 1g.10gb Dispositivo 2
-
MIG 1g.10gb Dispositivo 3
-
-
GPU 2 e GPU 3: stesso schema di GPU 0 e GPU 1
-
-
Completo GPUs (4-7): nessun partizionamento MIG
-
GPU 4: NVIDIA A100- -80 GB — GPU completa da 80 GB SXM4
-
GPU 5: NVIDIA A100- 80 GB — GPU completa da 80 GB SXM4
-
GPU 6: NVIDIA A100- 80 GB — GPU completa da 80 GB SXM4
-
GPU 7: NVIDIA A100- 80 GB — GPU completa da 80 GB SXM4
-
Una volta che l'operatore GPU NVIDIA crea le partizioni MIG, il driver NVIDIA DRA rileva automaticamente queste istanze isolate dall'hardware e le rende disponibili per l'allocazione dinamica delle risorse in Kubernetes. Il driver DRA rileva ogni istanza MIG con il suo profilo specifico (1g.10gb, 2g.20gb, 3g.40gb) e le espone come risorse pianificabili attraverso la classe del dispositivo. mig.nvidia.com
Il driver DRA monitora continuamente la topologia MIG e mantiene un inventario delle istanze disponibili in tutte. GPUs Quando un Pod richiede un profilo MIG specifico tramite aResourceClaimTemplate
, il driver DRA seleziona in modo intelligente l'istanza MIG appropriata da qualsiasi GPU disponibile, abilitando una vera multi-tenancy a livello hardware. Questa allocazione dinamica consente l'esecuzione simultanea di più carichi di lavoro isolati sulla stessa GPU fisica, mantenendo rigidi limiti di risorse e garanzie prestazionali.
Fase 2: Verificare l'allocazione delle risorse MIG
Vediamo ora alcuni esempi per dimostrare come DRA alloca dinamicamente le istanze MIG a diversi carichi di lavoro. Implementate resourceclaimtemplates
e testate i pod per vedere come il driver DRA colloca i carichi di lavoro tra le partizioni MIG disponibili, consentendo a più container di condividere le risorse GPU con isolamento a livello di hardware.
-
Crea
resourceclaimtemplates
per contenere il MIG:mig-claim-template.yaml
apiVersion: 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'
-
Applica i tre modelli:
kubectl apply -f mig-claim-template.yaml
-
Esegui il comando seguente:
kubectl get resourceclaimtemplates -n mig-gpu
Di seguito è riportato un output di esempio:
NAME AGE mig-large-template 71m mig-medium-template 71m mig-small-template 71m
-
Crea
mig-pod.yaml
per pianificare più lavori per sfruttare questoresourceclaimtemplates
vantaggio:--- # 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
-
Applica questa specifica, che dovrebbe implementare tre Pod:
kubctl apply -f mig-pod.yaml
Questi Pod devono essere programmati dal driver DRA.
-
Controllate i registri del Pod del driver DRA e vedrete un risultato simile a questo:
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**],}]
-
Verifica il
resourceclaims
per vedere lo stato del Pod:kubectl get resourceclaims -n mig-gpu -w
Di seguito è riportato un output di esempio:
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 0s
Come puoi vedere, tutti i Pod sono stati spostati dalla posizione in sospeso al
allocated,reserved
driver DRA. -
Esegui
nvidia-smi
dal nodo. Noterai che sono in esecuzione tre processori Python: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 |** +-----------------------------------------------------------------------------------------+
Ottimizza i carichi di lavoro della GPU con IMEX utilizzando 100 istanze P6e GB2
IMEX (Internode Memory Exchange) consente una comunicazione coerente in termini di memoria tra i nodi per la formazione distribuita su NVIDIA 00. GB2 UltraClusters
Effettuare le seguenti operazioni.
-
Definite un programma
ComputeDomain
per l'addestramento multinodo con un file denominatoimex-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
-
Definisci un Pod utilizzando i canali IMEX con un file denominato:
imex-pod.yaml
apiVersion: 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: NoSchedule
Nota
Ciò richiede istanze P6e 00. GB2
-
Implementa IMEX applicando i modelli and:
ComputeDomain
kubectl apply -f imex-claim-template.yaml kubectl apply -f imex-compute-domain.yaml kubectl apply -f imex-pod.yaml
-
Controlla lo stato.
ComputeDomain
kubectl get computedomain distributed-training-domain
-
Monitora la distribuzione del demone IMEX.
kubectl get pods -n nvidia-dra-driver -l [resource.nvidia.com/computeDomain](http://resource.nvidia.com/computeDomain)
-
Controlla i canali IMEX nel Pod:
kubectl exec imex-distributed-training -- ls -la /dev/nvidia-caps-imex-channels/
-
Visualizza i log del Pod:
kubectl logs imex-distributed-training
Di seguito è riportato un esempio di output previsto:
=== 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
Per ulteriori informazioni, vedere l'esempio di NVIDIA