Best practice per l'ottimizzazione dell'inferenza di modelli linguistici di grandi dimensioni con GPU su Google Kubernetes Engine (GKE)


Google Kubernetes Engine (GKE) offre un controllo granulare per i modelli linguistici di grandi dimensioni (LLM). (LLM) con prestazioni e costi ottimali. Questa guida descrive meglio per ottimizzare l'inferenza e la distribuzione di LLM aperti con GPU GKE utilizzando vLLM Inferenza della generazione di testo (TGI).

Per un elenco di controllo riepilogativo di tutte le best practice, consulta il riepilogo dell'elenco di controllo.

Obiettivi

Questa guida è rivolta ai clienti di AI generativa, agli utenti GKE nuovi o esistenti, agli ML Engineer e agli LLMOps (DevOps) Engineer interessati a ottimizzare i loro carichi di lavoro LLM utilizzando le GPU con Kubernetes.

Al termine di questa guida, potrai:

  • Scegli tecniche di ottimizzazione LLM post-addestramento, tra cui quantizzazione, parallelismo di tensori e ottimizzazione della memoria.
  • Valuta i compromessi di alto livello quando prendi in considerazione queste tecniche di ottimizzazione.
  • Eseguire il deployment di modelli LLM aperti su GKE utilizzando la pubblicazione come vLLM o TGI con impostazioni di ottimizzazione abilitate.

Panoramica delle tecniche di ottimizzazione della pubblicazione tramite LLM

A differenza dei carichi di lavoro non AI, i carichi di lavoro LLM in genere presentano una latenza più elevata e un throughput inferiore a causa della loro dipendenza dalle operazioni di moltiplicazione di matrici. Per migliorare le prestazioni di inferenza LLM, puoi utilizzare acceleratori hardware (ad esempio GPU e TPU) e distribuzione ottimizzata i modelli di machine learning.

Puoi applicare una o più delle seguenti best practice per ridurre i modelli LLM della latenza del carico di lavoro, migliorando al contempo la velocità effettiva e l'efficienza in termini di costi:

Gli esempi in questa guida utilizzano l'LLM Gemma 7B insieme framework di gestione vLLM o TGI per applicare queste best practice; tuttavia, concetti e funzionalità descritti si applicano agli LLM aperti più popolari.

Prima di iniziare

Prima di provare gli esempi in questa guida, completa queste attività preliminari:

  1. Segui le istruzioni riportate in queste guide per accedere al modello Gemma, preparare l'ambiente e creare e configurare le risorse Google Cloud:

    Assicurati di salvare il token di accesso a Hugging Face nel tuo secret Kubernetes.

  2. Clona il repository di esempi https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/ nel tuo locale di sviluppo software.

  3. Cambia la directory di lavoro in /kubernetes-engine-samples/ai-ml/llm-serving-gemma/.

Best practice: quantizzazione

La quantizzazione è una tecnica analoga alla compressione delle immagini con perdita di dati che riduce le dimensioni del modello rappresentando i pesi in formati di precisione inferiore (8 bit o 4 bit), riducendo così i requisiti di memoria. Tuttavia, come la compressione delle immagini, la quantizzazione comporta un compromesso: la riduzione delle dimensioni del modello può comportare una minore precisione.

Esistono vari metodi di quantizzazione, ciascuno con i suoi vantaggi e svantaggi unici. Alcuni, come AWQ e GPTQ, richiedono la prequantizzazione e sono disponibili su piattaforme come Hugging Face o Kaggle. Ad esempio, se applichi GPTQ al modello Llama-2 13B e AWQ al modello Gemma 7B, puoi pubblicare i modelli su una singola GPU L4 anziché su due GPU L4 senza quantizzazione.

Puoi anche eseguire la quantizzazione utilizzando strumenti come AutoAWQ e AutoGPTQ. Questi metodi possono migliorare di latenza e velocità effettiva. Al contrario, le tecniche che utilizzano EETQ e la biblioteca bitsandbytes per la quantizzazione non richiedono modelli prequantizzati, pertanto possono essere una scelta appropriata quando le versioni prequantizzate non sono disponibili.

La tecnica di quantizzazione migliore da utilizzare dipende dai tuoi scopi specifici e dalla compatibilità della tecnica con il framework di pubblicazione che vuoi utilizzare. Per saperne di più, consulta la guida alla quantizzazione di Hugging Face.

Seleziona una di queste schede per vedere un esempio di applicazione della quantizzazione utilizzando i framework TGI o vLLM:

TGI

GKE supporta queste opzioni di quantizzazione con TGI:

  • awq
  • gptq
  • eetq
  • bitsandbytes
  • bitsandbytes-nf4
  • bitsandbytes-fp4

I metodi di quantizzazione AWQ e GPTQ richiedono modelli pre-quantizzati, mentre EETQ e la quantizzazione di bitsandbytes può essere applicata a qualsiasi modello. Per scoprire di più su queste opzioni, consulta questo articolo su Hugging Face.

Per utilizzare la quantizzazione, imposta il parametro -–quantize all'avvio del server del modello.

Lo snippet seguente mostra come ottimizzare Gemma 7B con quantizzazione di bitsandbytes mediante TGI su GKE.

args:
- --model-id=$(MODEL_ID)
- --num-shard=2
- --quantize=bitsandbytes

Per applicare questa configurazione, utilizza il seguente comando:

kubectl apply -f tgi/tgi-7b-bitsandbytes.yaml

vLLM

GKE supporta queste opzioni di quantizzazione con vLLM:

Per utilizzare la quantizzazione del modello con vLLM, i modelli devono essere prequantizzati. Quando avvii il runtime, imposta il parametro –quantization.

Il seguente snippet mostra come ottimizzare il modello Gemma 7B con quantizzazione awq utilizzando vLLM su GKE:

args:
- --model=$(MODEL_ID)
- --tensor-parallel-size=1
- --quantization=awq
env:
- name: MODEL_ID
  value: google/gemma-7b-AWQ
resources:
  requests:
    nvidia.com/gpu: 1
  limits:
    nvidia.com/gpu: 1

Per applicare questa configurazione, utilizza il comando seguente:

kubectl apply -f vllm/vllm-7b-awq.yaml

Migliora la latenza utilizzando la quantizzazione della cache KV

Puoi utilizzare la quantizzazione della cache KV FP8 E5M2 per ridurre in modo significativo l'utilizzo di memoria della cache KV e migliorare la latenza, in particolare per dimensioni dei batch elevate. Tuttavia, questo riduce la precisione dell'inferenza.

Per attivare la quantizzazione della cache KV E5M2 FP8, imposta il parametro --kv-cache-dtype fp8_e5m2:

args:
- --model=$(MODEL_ID)
- --tensor-parallel-size=1
- --kv-cache-dtype=fp8_e5m2
- --max-model-len=1200
resources:
  requests:
    cpu: "2"
    memory: "25Gi"
    ephemeral-storage: "25Gi"
    nvidia.com/gpu: 1
  limits:
    cpu: "2"
    memory: "25Gi"
    ephemeral-storage: "25Gi"
    nvidia.com/gpu: 1

Per applicare questa configurazione, utilizza il comando seguente:

kubectl apply -f vllm/vllm-7b-kvcache.yaml

Best practice: parallelismo tensoriale

Il parallelismo dei Tensor è una tecnica che distribuisce il carico computazionale tra con più GPU, aspetto essenziale quando si eseguono modelli di grandi dimensioni che superano Capacità di memoria GPU. Questo approccio può essere più conveniente in quanto puoi utilizzare più GPU a prezzi accessibili invece di una sola costosa. Può anche per migliorare la velocità effettiva di inferenza del modello. Il parallelismo dei tensori sfrutta il fatto che le operazioni dei tensori possono essere eseguite in modo indipendente su blocchi di dati più piccoli.

Per scoprire di più su questa tecnica, consulta la guida al parallelismo dei Tensor di Hugging Face.

Seleziona una di queste schede per visualizzare un esempio di applicazione del parallelismo del tensore utilizzando i framework TGI o vLLM:

TGI

Con TGI, il runtime di pubblicazione utilizzerà tutte le GPU disponibili per il pod per impostazione predefinita. Puoi impostare il numero di GPU da utilizzare specificando il parametro --num-shard con il numero di GPU come valore.

Consulta la documentazione di Hugging Face per consultare l'elenco dei modelli supportati per il parallelismo dei tensori.

Lo snippet seguente mostra come ottimizzare Gemma 7B modello ottimizzato per le istruzioni utilizzando il parallelismo tensore e due GPU L4:

args:
- --model-id=$(MODEL_ID)
- --num-shard=2

Per applicare questa configurazione, utilizza il comando seguente:

kubectl apply -f tgi/tgi-7b-it-tensorparallelism.yaml

Nei cluster GKE Autopilot, l'esecuzione di questo comando crea un pod con requisiti minimi di risorse di 21 vCPU e 78 GiB di memoria.

vLLM

vLLM supporta l'inferenza parallela di tensori distribuiti. vLLM attiva la funzionalità per impostazione predefinita se è disponibile più di una GPU.

Lo snippet seguente mostra come ottimizzare il modello Gemma 7B ottimizzato per le istruzioni utilizzando il parallelismo tensoriale e due GPU L4:

args:
- --model=$(MODEL_ID)
- --tensor-parallel-size=2

Per applicare questa configurazione, utilizza il seguente comando:

kubectl apply -f vllm/vllm-7b-it-tensorparallelism.yaml

Nei cluster GKE Autopilot, l'esecuzione di questo comando crea un pod con requisiti minimi delle risorse di 21 vCPU e 78 GiB di memoria.

Best practice: ottimizzazione della memoria del modello

L'ottimizzazione dell'utilizzo della memoria degli LLM è fondamentale per un'inferenza efficiente. Questo illustra le strategie di ottimizzazione dello strato di attenzione, come per attirare l'attenzione, Queste strategie migliorano l'efficienza della memoria, consentendo sequenze di input più lunghe e tempi di inattività della GPU ridotti. Questa sezione descrive anche come regolare le dimensioni di input e output del modello in base alle limitazioni di memoria e ottimizzare per framework di pubblicazione specifici.

Ottimizzazione del livello di attenzione

I livelli di attenzione auto-consapevole consentono ai modelli di comprendere il contesto nelle attività di elaborazione del linguaggio, poiché il significato delle parole può variare a seconda del contesto. Tuttavia, questi livelli memorizzano i pesi dei token di input, le chiavi (K) e i valori (V) nella vRAM della GPU. Pertanto, con l'allungarsi della sequenza di input, si verifica una crescita quadratica delle dimensioni e del tempo di calcolo.

L'utilizzo della memorizzazione nella cache di valori-chiave è particolarmente utile quando si gestiscono lunghe sequenze di input, per le quali l'overhead dell'auto-attenzione può diventare significativo. Questo approccio all'ottimizzazione riduce l'elaborazione computazionale complessità lineare.

Le tecniche specifiche per ottimizzare i meccanismi di attenzione negli LLM includono:

  • Attenzione alle pagine. L'attenzione alle pagine migliora la gestione della memoria per e lunghe sequenze di input mediante tecniche di paging, simili Memoria virtuale del sistema operativo. In questo modo, si riducono efficacemente la frammentazione e la duplicazione nella cache KV, consentendo sequenze di input più lunghe senza esaurire la memoria della GPU.
  • Flash attention: Flash attention riduce i colli di bottiglia della memoria GPU riducendo al minimo i trasferimenti di dati tra la RAM GPU e la cache L1 durante la generazione dei token. In questo modo, viene eliminato il tempo di inattività dei core di calcolo, migliorando notevolmente le prestazioni di inferenza e addestramento per le GPU.

Ottimizzazione delle dimensioni di input e output del modello

I requisiti di memoria dipendono dalle dimensioni di input e output. Output più lungo e altro richiedono più risorse, mentre un output più breve e meno contesto possono consentire di utilizzando una GPU più piccola e più economica.

Seleziona una di queste schede per vedere un esempio di ottimizzazione dell'input e dell'output del modello requisiti di memoria nei framework TGI o vLLM:

TGI

Il runtime di pubblicazione TGI controlla i requisiti di memoria durante l'avvio e non si avvia se l'impronta di memoria massima del modello non è compatibile con la memoria GPU disponibile. Questo controllo elimina gli arresti anomali di OOM (out of memory) su carichi di lavoro che richiedono molta memoria.

GKE supporta i seguenti parametri TGI per ottimizzare i requisiti di memoria del modello:

Il seguente snippet mostra come puoi pubblicare un modello Gemma 7B ottimizzato per le istruzioni con una singola GPU L4, con le impostazioni dei parametri--max-total-tokens=3072, --max-batch-prefill-tokens=512, --max-input-length=512:

args:
- --model-id=$(MODEL_ID)
- --num-shard=1
- --max-total-tokens=3072 
- --max-batch-prefill-tokens=512
- --max-input-length=512
env:
- name: MODEL_ID
  value: google/gemma-7b

Per applicare questa configurazione, utilizza il seguente comando:

kubectl apply -f tgi/tgi-7b-token.yaml

vLLM

In vLLM, configura la lunghezza del contesto del modello, che influisce direttamente le dimensioni della cache dei valori chiave e i requisiti di RAM GPU. Se il contesto è di lunghezza ridotta, per l'uso di GPU più convenienti. Il valore predefinito è il massimo di token accettati dal modello. Limita la lunghezza massima del contesto con --max-model-len MAX_MODEL_LEN, se necessario.

Ad esempio, il modello ottimizzato per le istruzioni Gemma 7B, con una lunghezza del contesto predefinita di 8192, supera la capacità di memoria di una singola GPU NVIDIA L4. Per eseguire il deployment su un L4, limita la lunghezza combinata di prompt e output impostando --max-model-len su un valore inferiore a 640. Questo aggiustamento consente di eseguire il modello su una singola GPU L4 nonostante le sue grandi dimensioni la lunghezza del contesto.

Per eseguire il deployment con il limite di token modificato, utilizza il seguente snippet:

args:
- --model=$(MODEL_ID)
- --tensor-parallel-size=1
- --max-model-len=600

Per applicare questa configurazione, utilizza il comando seguente:

kubectl apply -f vllm/vllm-7b-token.yaml

Riepilogo elenco di controllo

Obiettivo di ottimizzazione Esercitati
Latenza
  • Dai la priorità alle GPU potenti: Valuta la possibilità di eseguire l'upgrade a GPU con capacità di calcolo più elevate velocità effettiva di I/O della memoria.
  • Esplora la quantizzazione: tecniche come AWQ possono migliorare la latenza, ma tieni presente i potenziali compromessi in termini di precisione.
Velocità effettiva
  • Scala in orizzontale: Aumenta il numero di repliche di pubblicazione (pod) per distribuire carico di lavoro.
  • Utilizza il parallelismo tensoriale: per i modelli di grandi dimensioni che superano la capacità di una singola GPU, utilizza il parallelismo tensoriale per distribuire i calcoli su più GPU. Per i più piccoli di replica, considera più repliche con parallelismo tensore pari a "1" per evitare spese eccessive.
  • Esegui richieste collettive e quantizzazione: combina le richieste ed esplora tecniche di quantizzazione che mantengono un'accuratezza accettabile.
Efficienza in termini di costi
  • Scegli modelli più piccoli: Seleziona i modelli di una famiglia adatti ai tuoi vincoli delle risorse budget.
  • Applica la quantizzazione: Usa la quantizzazione per ridurre i requisiti di memoria, in particolare quando che hanno a che fare con i modelli più grandi.
  • Limita la lunghezza del contesto: limita la lunghezza del contesto per ridurre ulteriormente l'utilizzo della memoria e consentire l'esecuzione su GPU più piccole e più convenienti.

Passaggi successivi