View a markdown version of this page

Inferenza del modello AI con scalabilità automatica sulle GPU con Amazon EKS - Amazon EKS

Contribuisci a migliorare questa pagina

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

Per contribuire a questa guida per l'utente, scegli il GitHub link Modifica questa pagina su che si trova nel riquadro destro di ogni pagina.

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

Inferenza del modello AI con scalabilità automatica sulle GPU con Amazon EKS

Suggerimento

Registrati ai prossimi AI/ML workshop Amazon EKS.

Questa sezione descrive i concetti e le procedure per la scalabilità automatica dei carichi di lavoro di inferenza AI su GPU con Amazon EKS.

La singola replica del modello VLLm che hai distribuito nella precedente sezione Load & Serve Models può soddisfare un numero limitato di richieste simultanee prima che le nuove richieste inizino ad attendere, il che aumenta la latenza e può causare timeout delle richieste. Per stare al passo con il traffico, puoi scalare automaticamente l'implementazione orizzontalmente. La scalabilità automatica aggiunge repliche del carico di lavoro all'aumentare della domanda e le rimuove quando la domanda diminuisce, in modo da evitare l'eccessivo provisioning della capacità della GPU.

La scalabilità automatica delle inferenze avviene in due fasi.

  • Scalabilità dei nodi: quando lo scheduler Kubernetes non ha spazio per posizionare nuovi pod sui nodi esistenti, i pod rimangono. Pending Karpenter risponde ai Pending pod fornendo nodi GPU adatti ad essi e rimuove i nodi quando le repliche del carico di lavoro diminuiscono.

  • Scalabilità tramite pod: l'Horizontal Pod Autoscaler (HPA) monitora una metrica configurata. Quando tale metrica supera una soglia configurata, HPA aumenta il numero di repliche del carico di lavoro e vengono creati nuovi pod VLLm.

La fase di scalabilità dei nodi fornisce la capacità della GPU necessaria per l'esecuzione delle repliche del carico di lavoro. La fase di scalabilità basata su pod regola il numero di repliche del carico di lavoro per mantenere la metrica scelta vicina all'obiettivo.

Provisioning dei nodi GPU con Karpenter

Karpenter gestisce il ciclo di vita dei nodi, effettuando il provisioning dei nodi quando i carichi di lavoro ne hanno bisogno e consolidando o rimuovendo i nodi quando non lo richiedono. Funziona con lo scheduler Kubernetes anziché sostituirlo. Lo scheduler posiziona i pod sui nodi. Karpenter fornisce la capacità per i pod che lo scheduler non può contenere, quindi consente allo scheduler di associarli una volta che il nodo è presente. Ready

Karpenter gestisce i nodi GPU in modo diverso rispetto a una flotta di nodi CPU.

Le GPU sono richieste come unità intere

A meno che non si utilizzi una tecnica di condivisione della GPU come time-slicing o MIG, un pod riceve una o più GPU intere anziché una frazione come farebbe con CPU o memoria. Ogni GPU ha la propria memoria dedicata, quindi le repliche sullo stesso nodo non condividono la memoria della GPU. Il modo in cui questo viene mappato ai nodi dipende dal tipo di istanza:

  • Single-GPU instance (ad esempiog6.xlarge) — Il nodo contiene esattamente una replica. Le repliche, le GPU e i nodi sono scalabili uno a uno e ogni replica è isolata sulla propria istanza.

  • Multi-GPU istanza (ad esempiog6.12xlarge, che ha 4 GPU): il plug-in del dispositivo pubblicizza il numero completo di GPU, quindi Karpenter può raggruppare diverse repliche su un nodo, una per GPU.

  • Multi-GPU pod: un pod può richiedere più di una GPU. Ad esempio, imposta lo shard nvidia.com/gpu: 2 di un modello di grandi dimensioni su due GPU e Karpenter posiziona il pod su un nodo con così tante GPU libere.

Karpenter ottimizza la disponibilità e i costi della GPU

Karpenter bilancia l'utilizzo della scarsa capacità della GPU con una gestione economicamente vantaggiosa:

  • Selezione delle istanze: data la flessibilità NodePool, Karpenter seleziona il tipo di istanza più economico adatto ai pod. Pending Quando un avvio raggiunge una capacità insufficiente, riprova automaticamente altri tipi di istanza e zone di disponibilità, il che aumenta le probabilità di esaurimento della capacità della GPU.

  • Consolidamento: quando la domanda diminuisce e le repliche aumentano, Karpenter recupera i nodi liberati. WhenEmptyOrUnderutilizedrimuove i nodi vuoti e riconfeziona le repliche su un numero inferiore di nodi, mentre WhenEmpty recupera un nodo solo dopo che non è stato pianificato nulla su di esso.

  • Protezione dei pod in volo: per evitare che i pod vengano interrotti durante il consolidamento, aggiungi l'karpenter.sh/do-not-disruptannotazione, imposta un PodDisruptionBudget o utilizza l'impostazione per ritardare il consolidamento. consolidateAfter

Una volta che Karpenter ha raggiunto la capacità della GPU, prende il sopravvento la fase di scalabilità dei pod: HPA aggiunge e rimuove le repliche in base alla metrica configurata. Il resto di questa sezione spiega come scegliere quella metrica di scalabilità per i carichi di lavoro di inferenza.

Scalabilità automatica tra GPU e CPU

In Kubernetes, i CPU-based carichi di lavoro tradizionali vengono scalati automaticamente immediatamente, ma l'inferenza no. GPU-based Esistono tre differenze principali:

Disponibilità delle metriche per la scalabilità automatica

Kubernetes fornisce metriche di CPU e memoria a HPA immediatamente

Il kubelet su ciascun nodo riporta l'utilizzo della CPU e della memoria all'API Kubernetes Metrics, in modo che HPA possa leggere questi valori direttamente e scalare i carichi di lavoro senza componenti aggiuntivi.

I carichi di lavoro accelerati richiedono metriche, configurazioni, esportatori e adattatori aggiuntivi

Il kubelet non riporta le metriche di GPU o di inferenza. Per scalare GPU-based l'inferenza, è necessario aggiungere gli esportatori che pubblicano i segnali pertinenti, come le metriche delle applicazioni VLLm e le metriche GPU dell'esportatore DCGM, e gli adattatori che espongono tali metriche a HPA.

Allocazione e condivisione delle risorse

I carichi di lavoro tradizionali condividono CPU e memoria in frazioni

I cgroup Linux dividono CPU e memoria in risorse frazionarie, permettendo a più pod di condividere lo stesso nodo. Un pod può richiedere una parte della capacità di un nodo, ad esempio 100 millicore di CPU o 512 MiB di memoria.

I carichi di lavoro accelerati allocano e condividono le GPU tramite un framework di allocazione GPU

Le GPU non sono condivise tramite cgroup come CPU e memoria. La configurazione Kubernetes più comune oggi utilizza il plug-in per dispositivi NVIDIA, che alloca intere GPU ai pod (ad esempio,). nvidia.com/gpu: 1 Dynamic Resource Allocation (DRA) è una nuova API Kubernetes che alloca le GPU tramite dichiarazioni di risorse, offrendo una pianificazione e una gestione delle risorse più flessibili. Sia il plug-in del dispositivo che il DRA possono supportare tecniche di condivisione della GPU. Time-slicing consente a più pod di condividere una GPU interlacciando l'accesso nel tempo, mentre GPU (MIG) partiziona le Multi-Instance GPU supportate, come NVIDIA A100 e H100, in istanze GPU isolate dall'hardware.

Segnali di scalabilità

I carichi di lavoro tradizionali in genere si adattano all'utilizzo della CPU e della memoria

L'utilizzo è il segnale di scalabilità automatica standard per i carichi di lavoro di CPU e memoria. È un indicatore di ritardo perché aumenta solo dopo che il carico di lavoro è già sotto carico, ma per molte applicazioni tradizionali è sufficiente per prendere decisioni sulla scalabilità.

I carichi di lavoro accelerati dovrebbero essere scalabili in base ai principali indicatori, non all'utilizzo della GPU

L'utilizzo della GPU (DCGM_FI_DEV_GPU_UTIL) indica se la GPU è occupata, non quanto è occupata. Poiché un server di inferenza come vLLM può rimanere vicino al 100% su un'ampia gamma di richieste in entrata, l'utilizzo è un segnale di scalabilità automatica inaffidabile. Scala invece in base agli indicatori principali che aumentano man mano che la domanda si avvicina alla capacità, come la profondità della coda delle richieste, il time to first token (TTFT) e la latenza delle richieste.

Di queste tre differenze sopra descritte, valuta attentamente i tuoi segnali di scalabilità. Poiché l'utilizzo della GPU non è un segnale ad alta confidenza della capacità di inferenza residua, è necessario identificare e raccogliere segnali che tengano traccia della domanda effettiva sul server di inferenza del modello.

La sezione successiva illustra quali segnali utilizzare come metriche di scalabilità e come interagiscono tra loro.

Scelta delle metriche di scalabilità

Nessuna metrica indica quando scalare le repliche di inferenza del modello, quindi la scalabilità si basa su una combinazione di segnali provenienti dal server di inferenza. Questi segnali interagiscono, ognuno dei quali si basa sul precedente per catturare la domanda prima e in modo più affidabile rispetto a qualsiasi metrica singola:

Signal Metrica Ruolo nella scalabilità

Queue

Profondità della coda delle richieste (numero di richieste in attesa di essere elaborate)

Un indicatore principale e il miglior trigger predefinito, perché nel momento in cui la domanda supera la capacità si forma una coda.

Latenza

Latenza di richiesta (latenza p95 o TTFT)

Attiva la scalabilità quando le risposte sono lente anche se la coda non si è ancora creata, mantenendo la latenza rivolta all'utente entro l'obiettivo.

Memoria GPU

Utilizzo della cache KV (quanto è piena la memoria di richiesta della GPU)

Protegge dall'esaurimento della memoria della GPU; quando si avvicina al limite, il server inizia a rifiutare o a mettere in coda le richieste.

Insieme costituiscono diversi livelli di difesa: la profondità della coda delle richieste è il fattore scatenante principale che si attiva nel momento in cui la domanda supera la capacità, la latenza delle richieste consente di controllare la lentezza delle risposte prima che si formi una coda e l'utilizzo della cache KV funge da backstop che impedisce l'esaurimento della memoria della GPU.

Mettere tutto in pratica

Le seguenti sottosezioni mostrano come far funzionare questi segnali con uno specifico autoscaler.

  • Trova le soglie metriche di scalabilità. Esegui il test di carico di una singola replica VLLm per individuarne il limite di capacità e le soglie di profondità e latenza della coda su cui basare la scalabilità. Inizia da qui.

  • Scalabilità con HPA e KEDA. Repliche VLLm in scala automatica con KEDA e Horizontal Pod Autoscaler, utilizzando la profondità della coda delle richieste e la latenza end-to-end come segnali di scalabilità.