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,eksctlselezionerà automaticamente l'AMI appropriata e installerà il NVIDIA Kubernetes Device Plugin. Per saperne di più, consulta il supporto per le GPU nella documentazione di eksctl.
Se invece decidi di utilizzare l'operatore EKS Accelerated AMIs e NVIDIA GPU
Per verificare che il GPUs NVIDIA Device Plugin sia attivo e sia esposto 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 molti tipi di istanze diversi EC2
L'utilizzo del maggior numero possibile di tipi di EC2 istanze diversi è una best practice importante per la scalabilità su Amazon EKS, come indicato nella Piano dati Kubernetes sezione. Questa raccomandazione si applica anche alle istanze con hardware accelerato (ad es.). GPUs Se crei un cluster che utilizza un solo tipo di istanza e provi a scalare il numero di nodi oltre la capacità della regione, potresti ricevere un errore di capacità insufficiente (ICE), che indica che non sono disponibili istanze. È importante comprendere le caratteristiche uniche dei AI/ML carichi di lavoro prima di diversificare arbitrariamente. Esamina i tipi di istanze disponibili utilizzando lo strumento EC2 Instance Type Explorer
Le istanze di calcolo accelerato sono offerte in diversi modelli di acquisto per carichi di lavoro a breve, medio termine e stazionari. Per carichi di lavoro a breve termine, flessibili e tolleranti ai guasti, in cui vorresti evitare di effettuare una prenotazione, dai un'occhiata alle istanze Spot. I blocchi di capacità, le istanze On-Demand e i piani di risparmio consentono di fornire istanze di elaborazione accelerate per carichi di lavoro a medio e lungo termine. Per aumentare le possibilità di accedere correttamente alla capacità richiesta nell'opzione di acquisto preferita, si consiglia di utilizzare un elenco diversificato di tipi di istanze e zone di disponibilità. In alternativa, se ICEs riscontri un modello di acquisto specifico, riprova a utilizzare un modello diverso.
Esempio L'esempio seguente mostra come consentire a un Karpenter di effettuare il provisioning NodePool di istanze G e P superiori alla terza generazione (ad esempio, p3). Per ulteriori informazioni, consulta la sezione Le migliori pratiche di scalabilità EKS.
- 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
Per i dettagli sull'utilizzo delle istanze Spot per GPUs, consulta «Prendi in considerazione l'utilizzo di istanze Amazon EC2 Spot per GPUs Karpenter» di seguito.
Prendi in considerazione l'utilizzo di Amazon EC2 Spot Instances per GPUs Karpenter
Le istanze Amazon EC2 Spot consentono di sfruttare la EC2 capacità inutilizzata nel cloud AWS e sono disponibili con uno sconto fino al 90% rispetto ai prezzi On-Demand. Le istanze Amazon EC2 Spot possono essere interrotte con un preavviso di due minuti quando è EC2 necessario ripristinare la capacità. Per ulteriori informazioni, consulta le istanze Spot nella Amazon EC2 User Guide. Amazon EC2 Spot può essere un'ottima scelta per carichi di lavoro con tolleranza ai guasti, stateless e flessibili (tempo e tipo di istanza). Per ulteriori informazioni su quando utilizzare le istanze Spot, consulta le best practice delle istanze Spot. EC2 Puoi anche utilizzare le istanze Spot per AI/ML carichi di lavoro se sono compatibili con Spot.
Casi d'uso
I carichi di lavoro compatibili con Spot possono essere big data, carichi di lavoro containerizzati, CI/CD, server Web stateless, High Performance Computing (HPC) e carichi di lavoro di rendering. Le istanze Spot non sono adatte per carichi di lavoro rigidi, stateful, intolleranti ai guasti o strettamente accoppiati tra i nodi di istanza (ad esempio, carichi di lavoro con processi paralleli che dipendono fortemente l'uno dall'altro per il calcolo, che richiedono una comunicazione costante tra i nodi, come applicazioni di calcolo ad alte prestazioni basate su MPI come la fluidodinamica computazionale o i database distribuiti con interdipendenze complesse). Ecco i casi d'uso specifici che consigliamo (in nessun ordine particolare):
-
Inferenza online in tempo reale: utilizza le istanze Spot per una scalabilità ottimizzata in termini di costi per i carichi di lavoro di inferenza in tempo reale, a condizione che i carichi di lavoro siano adatti allo spot. In altre parole, il tempo di inferenza è inferiore a due minuti, l'applicazione è tollerante ai guasti alle interruzioni e può essere eseguita su diversi tipi di istanze. Garantisci l'elevata disponibilità attraverso la diversità delle istanze (ad esempio, tra più tipi di istanze e zone di disponibilità) o le prenotazioni, implementando al contempo la tolleranza agli errori a livello di applicazione per gestire potenziali interruzioni Spot.
-
Ottimizzazione iperparametrica: utilizza le istanze Spot per eseguire lavori di ottimizzazione esplorativa in modo opportuno, poiché le interruzioni possono essere tollerate senza perdite significative, soprattutto per esperimenti di breve durata.
-
Aumento dei dati: utilizza le istanze Spot per eseguire attività di preelaborazione e aumento dei dati che possono essere riavviate dai checkpoint se interrotte, il che le rende ideali per la disponibilità variabile di Spot.
-
Modelli di ottimizzazione: utilizza le istanze Spot per la messa a punto con solidi meccanismi di checkpoint per riprendere dall'ultimo stato salvato, riducendo al minimo l'impatto delle interruzioni delle istanze.
-
Inferenza in batch: utilizza le istanze Spot per elaborare grandi batch di richieste di inferenza offline in non-real-time modo da mettere in pausa e riprendere i lavori, offrendo il miglior allineamento con i risparmi sui costi di Spot e gestendo potenziali interruzioni attraverso nuovi tentativi o diversificazione.
-
Sottoinsiemi di formazione opportunistici: utilizza le istanze Spot per carichi di lavoro di formazione marginali o sperimentali (ad esempio, modelli più piccoli con meno di 10 milioni di parametri), dove le interruzioni sono accettabili e possono essere applicate ottimizzazioni dell'efficienza come la diversificazione tra tipi di istanze o regioni, sebbene non sia consigliabile per la formazione su scala di produzione a causa di potenziali interruzioni.
Considerazioni
Per utilizzare le istanze Spot per carichi di lavoro accelerati su Amazon EKS, ci sono una serie di considerazioni chiave (in nessun ordine particolare):
-
Usa Karpenter per gestire le istanze Spot con il consolidamento avanzato abilitato. Specificando karpenter.sh/capacity-type come «spot» in Karpenter, Karpenter eseguirà il provisioning delle istanze Spot per impostazione predefinita senza alcuna configurazione aggiuntiva. NodePool Tuttavia, per abilitare il Spot-to-Spot consolidamento avanzato, che sostituisce i nodi Spot sottoutilizzati con alternative Spot più economiche, è necessario abilitare il feature gate impostando --feature-gates =true negli argomenti del controller Karpenter o tramite la variabile di ambiente FEATURE_GATES. SpotToSpotConsolidation
SpotToSpotConsolidation Karpenter utilizza la strategia di allocazione per effettuare il provisioning delle istanze. price-capacity-optimized EC2 In base NodePool ai requisiti e ai vincoli dei pod, Karpenter racchiude i pod non programmabili e invia un set diversificato di tipi di istanze all'API Amazon Fleet. EC2 Puoi utilizzare lo strumento EC2 Instance Type Explorer per generare un elenco di tipi di istanze che soddisfano i tuoi requisiti di calcolo specifici. -
Assicurati che i carichi di lavoro siano stateless, tolleranti ai guasti e flessibili. I carichi di lavoro devono essere stateless, tolleranti ai guasti e flessibili in termini di dimensioni. instance/GPU Ciò consente una ripresa senza interruzioni dopo le interruzioni di Spot e la flessibilità delle istanze consente di rimanere potenzialmente su Spot più a lungo. Abilita la gestione delle interruzioni Spot
in Karpenter configurando il valore settings.InterruptionQueue Helm con il nome della coda AWS SQS per catturare gli eventi di interruzione Spot. Ad esempio, durante l'installazione tramite Helm, usa --set «settings.interruptionQueue=$ {CLUSTER_NAME}». Per vedere un esempio, consulta la guida Getting Started with Karpenter. Quando Karpenter rileva un evento di interruzione Spot, cordone, contamina, drena e chiude automaticamente i nodi prima dell'evento di interruzione per massimizzare il periodo di tolleranza di terminazione dei pod. Allo stesso tempo, Karpenter avvierà immediatamente un nuovo nodo in modo che possa essere pronto il prima possibile. -
Evitate di limitare eccessivamente la selezione del tipo di istanza. Dovreste evitare il più possibile di vincolare i tipi di istanza. Non limitando i tipi di istanze, vi è una maggiore possibilità di acquisire capacità Spot su larga scala con una frequenza inferiore di interruzioni delle istanze Spot a un costo inferiore. Ad esempio, evita di limitarti a tipi specifici (ad esempio g5.xlarge). Prendi in considerazione la possibilità di specificare un insieme diversificato di categorie e generazioni di istanze utilizzando chiavi come karpenter.k8s. aws/instance-category and karpenter.k8s.aws/instance-generation. Karpenter enables easier diversification of on-demand and Spot instance capacity across multiple instance types and Availability Zones (AZs). Moreover, if your AI/MLil carico di lavoro richiede un numero specifico o limitato di acceleratori ma è flessibile tra le regioni, puoi utilizzare Spot Placement Score per identificare dinamicamente la regione ottimale in cui distribuire il carico di lavoro prima del lancio.
-
Amplia NodePool i requisiti per includere un numero maggiore di famiglie di istanze simili. EC2 Ogni pool di istanze Spot è costituito da una capacità di EC2 istanze inutilizzata per un tipo di istanza specifico in una zona di disponibilità (AZ) specifica. Quando Karpenter tenta di fornire un nuovo nodo, seleziona un tipo di istanza che soddisfa i requisiti del nodo. NodePool Se nessun tipo di istanza compatibile dispone della capacità Spot in qualsiasi zona, il provisioning fallisce. Per evitare questo problema, consenti istanze della serie g più ampie (generazione 4 o superiore) di NVIDIA di diverse dimensioni e zone di disponibilità (AZs), tenendo conto delle esigenze hardware come la memoria GPU o il Ray Tracing. Poiché le istanze possono essere di diversi tipi, devi assicurarti che il tuo carico di lavoro sia in grado di funzionare su ogni tipo e che le prestazioni ottenute soddisfino le tue esigenze.
-
Sfrutta tutte le zone di disponibilità in una regione. La capacità disponibile varia in base alla zona di disponibilità (AZ), un tipo di istanza specifico potrebbe non essere disponibile in una zona ma abbondante in un'altra. Ogni combinazione unica di un tipo di istanza e una zona di disponibilità costituisce un pool di capacità Spot separato. Richiedendo la capacità AZs in tutte le aree geografiche che rientrano nei NodePool requisiti richiesti da Karpenter, è possibile cercare in modo efficace più pool contemporaneamente. Ciò massimizza il numero di pool di capacità Spot e quindi aumenta la probabilità di acquisire capacità Spot. Per ottenere ciò, nella NodePool configurazione, ometti completamente la chiave topology.kubernetes.io/zone per consentire a Karpenter di selezionare tra tutte le opzioni disponibili AZs nella regione, oppure AZs elenca esplicitamente utilizzando l'operatore: In e fornisci i valori (ad esempio, us-west-2a).
-
Prendi in considerazione l'utilizzo di Spot Placement Score (SPS) per avere visibilità sulla probabilità di accedere con successo alla capacità richiesta utilizzando le istanze Spot. Spot Placement Score (SPS) è uno strumento che fornisce un punteggio per aiutarti a valutare la probabilità di successo di una richiesta Spot. Quando utilizzi SPS, devi prima specificare i requisiti di elaborazione per le tue istanze Spot, quindi Amazon EC2 restituisce le prime 10 regioni o zone di disponibilità (AZs) in cui è probabile che la tua richiesta Spot abbia successo. Le regioni e le zone di disponibilità vengono valutate su una scala da 1 a 10. Un punteggio pari a 10 indica che è molto probabile, ma non è garantito che la richiesta Spot abbia successo. Un punteggio di 1 indica che la tua richiesta Spot ha bassissime probabilità di successo. Lo stesso punteggio potrebbe essere restituito per diverse regioni o zone di disponibilità. Per ulteriori informazioni, consulta la Guida alla creazione di una dashboard Spot Placement Score Tracker su AWS. Poiché la capacità di Spot oscilla continuamente, SPS ti aiuterà a identificare la combinazione di tipi di istanze e regioni più adatta ai tuoi vincoli di carico di lavoro (ad esempio flessibilità, prestazioni, dimensioni, ecc.). AZs Se il AI/ML carico di lavoro richiede un numero specifico o limitato di acceleratori ma è flessibile tra le regioni, puoi utilizzare il punteggio di posizionamento di Spot per identificare dinamicamente la regione ottimale in cui distribuire il carico di lavoro prima del lancio. Per aiutarti a scoprire automaticamente la probabilità di acquisire capacità Spot, forniamo una guida per la creazione di una dashboard di monitoraggio SPS. Questa soluzione monitora i punteggi SPS nel tempo utilizzando una configurazione YAML per configurazioni diversificate (ad esempio, requisiti di istanza inclusi GPUs), archivia le metriche e fornisce dashboard per confrontare le configurazioni. CloudWatch Definisci dashboard per carico di lavoro per valutare le esigenze di vCPU, memoria e GPU, garantendo configurazioni ottimali per i cluster EKS, inclusa la possibilità di utilizzare altre regioni AWS. Per saperne di più, consulta Come funziona il punteggio di posizionamento di Spot.
-
Gestisci con garbo le interruzioni e i test di Spot. Per un pod con un periodo di terminazione superiore a due minuti, il vecchio nodo verrà interrotto prima della riprogrammazione dei pod, il che potrebbe influire sulla disponibilità del carico di lavoro. Prendi in considerazione l'avviso di interruzione Spot di due minuti durante la progettazione delle tue applicazioni, implementa il checkpoint nelle applicazioni a lunga esecuzione (ad esempio, salvando i progressi su uno storage persistente come Amazon S3) per riprenderlo dopo le interruzioni, estendi i terminationGracePeriod secondi (l'impostazione predefinita è 30 secondi) nelle specifiche del Pod per consentire più tempo per uno spegnimento regolare e gestisci le interruzioni utilizzando i and/or segnali SIGTERM del ciclo di vita PreStop all'interno dell'applicazione per attività di spegnimento regolari come pulizia, salvataggio dello stato e chiusura della connessione. Per i carichi di lavoro in tempo reale, in cui il tempo di scalabilità è importante e i carichi di lavoro impiegano più di due minuti prima che l'applicazione sia pronta a servire il traffico, prendi in considerazione l'ottimizzazione dei tempi di avvio dei container e di caricamento dei modelli ML mediante revisioni Storage e Scalabilità e prestazioni delle applicazioni best practice. Per testare un nodo sostitutivo, usa AWS Fault Injection Service
(FIS) per simulare le interruzioni Spot.
Oltre a queste best practice principali di Spot, tieni conto di questi fattori nella gestione dei carichi di lavoro delle GPU su Amazon EKS. A differenza dei carichi di lavoro basati su CPU, i carichi di lavoro su GPU sono particolarmente sensibili ai dettagli hardware, come le funzionalità della GPU e la memoria GPU disponibile. I carichi di lavoro GPU potrebbero essere limitati dai tipi di istanze che possono utilizzare, con un minor numero di opzioni disponibili rispetto a. CPUs Come primo passo, valuta se il tuo carico di lavoro è flessibile a seconda delle istanze. Se non sai quanti tipi di istanze possono essere utilizzati dal tuo carico di lavoro, testali singolarmente per garantire compatibilità e funzionalità. Identifica quanto puoi essere flessibile per diversificare il più possibile, confermando al contempo che la diversificazione mantiene il carico di lavoro funzionante e comprendi eventuali impatti sulle prestazioni (ad esempio, sulla produttività o sui tempi di completamento). Nell'ambito della diversificazione dei carichi di lavoro, considera quanto segue:
-
Esamina la compatibilità tra CUDA e framework. I carichi di lavoro della GPU potrebbero essere ottimizzati per hardware o tipi di GPU specifici (ad esempio, V100 in p3 rispetto a A100 in p4) o scritti per versioni CUDA specifiche per librerie come, ad esempio TensorFlow, assicurati di verificare la compatibilità per i tuoi carichi di lavoro. Questa compatibilità è fondamentale per prevenire errori di runtime, arresti anomali, guasti nell'accelerazione della GPU (ad esempio, versioni CUDA non corrispondenti con framework simili PyTorch o che TensorFlow possono impedirne l'esecuzione) o la capacità di sfruttare funzionalità hardware come FP16/INT8 precision.
-
Memoria GPU. Assicurati di valutare i requisiti di memoria dei tuoi modelli e di profilare l'utilizzo della memoria del modello durante l'esecuzione utilizzando strumenti come DCGM Exporter
e imposta la memoria GPU minima richiesta per il tipo di istanza in etichette note come karpenter.k8s.aws/. instance-gpu-memory La VRAM della GPU varia in base al tipo di istanza (ad esempio, NVIDIA T4 ha 16 GB, A10G ha 24 GB, V100 ha 16-32 GB) e i modelli ML (ad esempio, modelli a linguaggio di grandi dimensioni) possono superare la memoria disponibile, causando errori out-of-memory (OOM) o arresti anomali. Per le istanze Spot in EKS, ciò può limitare la diversificazione. Ad esempio, non è possibile includere tipi di VRAM inferiori se il modello non è adatto, il che potrebbe limitare l'accesso ai pool di capacità e aumentare il rischio di interruzione. Tieni presente che per l'inferenza a singola GPU e a nodo singolo (ad esempio, più pod pianificati sullo stesso nodo per utilizzare le relative risorse GPU), ciò potrebbe limitare la diversificazione, poiché nella configurazione Spot puoi includere solo tipi di istanze con VRAM sufficiente. -
Precisione e prestazioni a virgola mobile. Non tutte le architetture GPU Nvidia hanno la stessa precisione a virgola mobile (ad esempio,/). FP16 INT8 Valuta le prestazioni dei tipi di core (CUDA/Tensor/RT) e la precisione a virgola mobile necessarie per i tuoi carichi di lavoro. L'esecuzione su una GPU meno costosa e meno performante non significa che sia migliore, quindi valuta la possibilità di valutare le prestazioni in termini di lavoro completato entro un periodo di tempo specifico per comprendere l'impatto della diversificazione.
Scenario: diversificazione per carichi di lavoro di inferenza in tempo reale
Per un carico di lavoro di inferenza online in tempo reale sulle istanze Spot, puoi configurare un Karpenter in modo che si diversifichi tra famiglie e generazioni di istanze NodePool GPU compatibili. Questo approccio garantisce un'elevata disponibilità attingendo a più pool Spot, mantenendo al contempo le prestazioni attraverso vincoli sulle funzionalità, sulla memoria e sull'architettura della GPU. Supporta l'utilizzo di alternative quando la capacità dell'istanza è limitata, riducendo al minimo le interruzioni e ottimizzando la latenza di inferenza. Questo esempio NodePool indica che utilizza istanze delle serie g e p maggiori di 3, con più di 20 GB di memoria GPU.
Esempio
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
Implementa il checkpointing per lavori di formazione di lunga durata
Il checkpointing è una tecnica di tolleranza ai guasti che prevede il salvataggio periodico dello stato di un processo, consentendone la ripresa dall'ultimo punto salvato in caso di interruzioni. Nell'apprendimento automatico, è comunemente associato alla formazione, in cui i lavori di lunga durata possono far risparmiare peso al modello e gli stati dell'ottimizzatore per riprendere l'addestramento dopo guasti, come problemi hardware o interruzioni delle istanze Spot.
I checkpoint vengono utilizzati per salvare lo stato dei modelli di machine learning (ML) durante l'addestramento. I checkpoint sono istantanee del modello e possono essere configurati tramite le funzioni di callback dei framework ML. È possibile utilizzare i checkpoint salvati per riavviare un processo di addestramento dall'ultimo checkpoint salvato. Utilizzando i checkpoint, si salvano le istantanee del modello durante l'addestramento a causa di un'interruzione imprevista del processo o dell'istanza di formazione. Ciò consente di riprendere l'addestramento del modello in futuro da un checkpoint. Oltre a implementare un sistema di resilienza dei nodi, consigliamo di implementare il checkpoint per mitigare l'impatto delle interruzioni, incluse quelle causate da guasti hardware o interruzioni delle istanze Amazon Spot. EC2
Senza checkpoint, le interruzioni possono comportare uno spreco di tempo di elaborazione e una perdita di progressi, il che è costoso per i lavori di formazione di lunga durata. Il checkpointing consente ai lavori di salvare periodicamente il loro stato (ad esempio, pesi del modello e stati dell'ottimizzatore) e di riprendere dall'ultimo checkpoint (ultimo batch elaborato) dopo un'interruzione. Per implementare il checkpointing, progetta la tua applicazione in modo che elabori i dati in grandi batch e salvi i risultati intermedi su uno storage persistente, ad esempio un bucket Amazon S3 tramite il driver Mountpoint for Amazon S3 CSI mentre il processo di formazione procede.
Casi d'uso
Il checkpointing è particolarmente utile in scenari specifici per bilanciare la tolleranza agli errori con il sovraccarico delle prestazioni. Prendi in considerazione l'utilizzo del checkpoint nei seguenti casi:
-
La durata del lavoro supera alcune ore: per lavori di formazione di lunga durata (ad esempio, più di 1-2 ore per modelli di piccole dimensioni o days/weeks per modelli di base di grandi dimensioni con miliardi di parametri), in cui la perdita di progressi a causa delle interruzioni è costosa. I lavori più brevi potrebbero non giustificare le spese generali. I/O
-
Per istanze Spot o guasti hardware: in ambienti soggetti a interruzioni, come EC2 Spot (preavviso di 2 minuti) o guasti hardware (ad esempio errori di memoria della GPU), il checkpoint consente una ripresa rapida, rendendo Spot fattibile per ridurre i costi in carichi di lavoro con tolleranza ai guasti.
-
Formazione distribuita su larga scala: per le configurazioni con acceleratori (ad esempio, >100), in cui il tempo medio tra i guasti diminuisce linearmente con la hundreds/thousands scala. GPUs Utilizzalo per il model/data parallelismo per gestire l'accesso simultaneo ai checkpoint ed evitare riavvii completi.
-
Modelli su larga scala con un elevato fabbisogno di risorse: nella formazione LLM su scala petabyte, in cui i guasti sono inevitabili a causa delle dimensioni del cluster, gli approcci su più livelli (rapido, locale ogni 5-30 minuti per i transitori, duraturo ogni ora per i guasti più gravi) ottimizzano i tempi di ripristino rispetto all'efficienza.
Utilizza 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à di svolgere 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 un periodo, 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 capacityReservationSelectorTermsVedi 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 riportate 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 tuoi 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 di Capacity Blocks.
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.drawpower.limitSe questo rapporto è pari o superiore al 100%, i tuoi codici stanno utilizzando appieno la capacità di calcolo della GPU. -
Il
-l 5flag 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 i 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 contribuire ad 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
Readye 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. Ad 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
-
Usa 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 UltraServers
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.
ConfigMapsCiò 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.
resourceclaimsCiò 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:
computeDomainsabilita 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
ResourceClaimspecifica 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 UltraServers
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.33o 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.1o 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 consentire 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 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.yamlvalori 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/v1beta1Di seguito è riportato l'output previsto:
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 -
Controlla le classi di dispositivi disponibili:
kubectl get deviceclassesDi 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 4h39mQuando 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.comslice 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.comslice crea un singolo dominio di calcolo che rappresenta l'intero contesto di calcolo della GPU. -
Questi
resourceslicesvengono quindi pubblicati sul server API Kubernetes, rendendo le risorse della GPU disponibili per la pianificazione.resourceclaimsLo 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 resourceslicesDi 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
ResourceClaimTemplateper 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-test1Di seguito è riportato un output di esempio:
NAME AGE single-gpu 9m16s -
Crea un Pod che usi il
ResourceClaimTemplatecon 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-test1Di seguito è riportato un esempio di output previsto:
NAME READY STATUS RESTARTS AGE gpu-pod 1/1 Running 0 13m -
Controlla lo
ResourceClaimstato:kubectl get resourceclaims -n gpu-test1Di 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-test1Di 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 in modo significativo 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
ResourceClaimTemplateper 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 -wDi 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
pendingallocated,reservedalrunning
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
ResourceClaimTemplateper 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 -wDi 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.yamldriver: 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.yamlfile:helm install gpu-operator nvidia/gpu-operator \ --namespace gpu-operator \ --create-namespace \ --version v25.3.1 \ --values gpu-operator-values.yamlQuesto 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-operatorDi 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 IDNVIDIA 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 -LDovresti 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
Eseguiamo 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
resourceclaimtemplatesper contenere il MIG:mig-claim-template.yamlapiVersion: 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-gpuDi seguito è riportato un output di esempio:
NAME AGE mig-large-template 71m mig-medium-template 71m mig-small-template 71m -
Crea
mig-pod.yamlper pianificare più lavori per sfruttare questoresourceclaimtemplatesvantaggio:--- # 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.yamlQuesti 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
resourceclaimsper vedere lo stato del Pod:kubectl get resourceclaims -n mig-gpu -wDi 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 0sCome puoi vedere, tutti i Pod sono stati spostati dalla posizione in sospeso al
allocated,reserveddriver DRA. -
Esegui
nvidia-smidal 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 UltraServers
Effettuare le seguenti operazioni.
-
Definite un programma
ComputeDomainper 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.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: NoScheduleNota
Ciò richiede istanze P6e 00. GB2
-
Implementa IMEX applicando i modelli and:
ComputeDomainkubectl apply -f imex-claim-template.yaml kubectl apply -f imex-compute-domain.yaml kubectl apply -f imex-pod.yaml -
Controlla lo stato.
ComputeDomainkubectl get computedomain distributed-training-domain -
Monitora la distribuzione del demone IMEX.
kubectl get pods -n nvidia-dra-driver -l 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-trainingDi 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