Turbocharging Llama 2 70B con NVIDIA H100

Il viaggio dell'inferenza LLM accelerata

The journey of accelerated LLM inference

La ricerca delle prestazioni nel motore di risposta di Perplexity ci spinge ad adottare le tecnologie più recenti offerte da NVIDIA e AWS. In questo blog, siamo entusiasti di condividere i risultati dei nostri ultimi esperimenti: un confronto dell'inferenza di Llama 2 70B su varie configurazioni hardware e software.

La nostra piattaforma di inferenza LLM, pplx-api, si basa su uno stack all'avanguardia alimentato da librerie open source. Dal momento in cui è iniziata la beta pubblica di pplx-api in ottobre, abbiamo affrontato sfide di scalabilità e abbiamo imparato come ottimizzare al meglio la nostra configurazione per raggiungere una scala massiccia. Ciò ci ha portato a condurre esperimenti con le seguenti domande guida:

Qual è il guadagno di prestazioni grezze passando le nostre GPU da NVIDIA A100 a NVIDIA H100, mantenendo invariate tutte le altre impostazioni?

Qual è il guadagno di efficienza della quantizzazione a virgola mobile a 8 bit (fp8), per la quale H100 aggiunge il supporto nativo? Qual è il costo in termini di precisione di questa quantizzazione?

In che modo il parallelismo dei tensori e la dimensione del batch influenzano la latenza e il throughput dei token?

Considerando quanto sopra, quale configurazione porta all'equilibrio più scalabile tra prestazioni ed efficienza dei costi?

Configurazione sperimentale

Abbiamo eseguito il seguente esperimento come una serie di benchmark locali per evitare la latenza di rete.

Metriche chiave:

Latenza: il tempo totale necessario al server di inferenza per generare la sua risposta completa.

Throughput: il numero di token di output, per secondo, per GPU, che il server di inferenza può generare per tutti gli utenti e le richieste.

Costanti:

I seguenti fattori influenzerebbero le metriche chiave, quindi li abbiamo mantenuti coerenti in diverse prove dell'esperimento.

Modello di IA

Le prestazioni scalano con le dimensioni dell'LLM. Più parametri richiedono più calcoli, con conseguente inferenza più lenta. Ad esempio, Llama 2 13B è più veloce di Llama 2 70B quando le altre impostazioni sono uguali. In questo esperimento utilizziamo Llama 2 70B perché vogliamo ottimizzare il servizio dei modelli open source più performanti.

Dataset di token di input/output

La quantità di token di input e output in ogni coppia di richiesta/risposta di esempio può influenzare le misurazioni delle prestazioni. In generale, la generazione dei token di output domina il tempo di risposta complessivo. Quando il campionamento dei dati induce solo risposte "sì/no" dall'LLM, la risposta è più veloce rispetto ai campioni che chiedono all'LLM di scrivere saggi. Il nostro dataset è composto da richieste sintetiche con 1024 token di input che inducono 512 token di output. Questa distribuzione è stata scelta per corrispondere alla distribuzione del traffico osservata sul nostro deployment pubblico di Llama2 70B.

Versione software

NVIDIA TensorRT-LLM (versione v0.5.0) è una libreria open source per l'ottimizzazione dell'inferenza LLM. Rilasciata a fine 2023, sintetizza le numerose ottimizzazioni di inferenza di NVIDIA e fornisce un livello flessibile di personalizzazione per i parametri chiave di questo esperimento: dimensione del batch, quantizzazione e parallelismo dei tensori.

Variabili

Abbiamo sperimentato su 4 assi di configurazione: parallelismo dei tensori, architettura GPU, quantizzazione e dimensione massima del batch. Questi assi sono interconnessi perché rappresentano ciascuno un compromesso rispetto alla risorsa critica di collo di bottiglia: la memoria della GPU.

Architettura GPU

L'architettura GPU Hopper di nona generazione (H100-HBM3-80GB / p5.48xlarge) racchiude un vasto elenco di funzionalità rispetto al suo predecessore, Ampere (A100-SXM4-80GB / p4de.24xlarge), inclusi tassi di calcolo da 2x a 6x e una larghezza di banda della memoria GPU quasi doppia. La larghezza di banda della memoria della GPU è una metrica critica per l'inferenza perché un collo di bottiglia primario della latenza dell'inferenza delle moltiplicazioni di matrici deriva dal caricamento di gigabyte di dati del modello dalla memoria della GPU nei registri di calcolo. Sulla base di queste statistiche, abbiamo ipotizzato che un confronto diretto tra NVIDIA H100 e A100 mostrerà un miglioramento di 2x sia nella latenza che nel throughput.

Un'altra differenza chiave tra NVIDIA H100 e A100 è che il core tensore H100 aggiunge nativamente il supporto per istruzioni a virgola mobile a 8 bit (fp8), il che apre la porta a ulteriori ottimizzazioni descritte di seguito. Ecco perché utilizziamo specificamente fp8 e fp16 per l'H100.

Per mantenere costante la memoria per GPU in questo esperimento, abbiamo utilizzato nodi con memoria GPU 8x80GB sia per le nostre NVIDIA A100 che H100. Oltre a consentire dimensioni di batch più elevate, la memoria della GPU è importante perché i parametri del modello vengono caricati nella memoria della GPU all'avvio del server per un accesso rapido. Ad esempio, se ciascuno dei 70 miliardi di parametri nel nostro modello è un numero a virgola mobile a 16 bit, allora il modello ha una dimensione di circa 140 GB, che non si adatta a una singola GPU. Da qui la necessità del parallelismo dei tensori, che spieghiamo di seguito.

Parallelismo dei tensori

Il parallelismo dei tensori si riferisce al numero di dispositivi GPU consumati per eseguire il server di inferenza. Quando assegniamo un numero di GPU, TensorRT-LLM mette in comune le loro risorse per aiutarci a raggiungere il budget di memoria minimo richiesto per eseguire Llama2 70B. La nostra ipotesi è che un parallelismo dei tensori inferiore comporterà una latenza più elevata (a causa di meno risorse consumate per soddisfare ogni batch) ma un throughput più elevato per GPU (grazie a un miglior utilizzo) rispetto a un parallelismo dei tensori più elevato.

Quantizzazione

La quantizzazione è la riduzione della precisione nei pesi e nelle attivazioni utilizzati dalle reti neurali. Utilizziamo questa tecnica per dimezzare il consumo di memoria della GPU quando passiamo da fp16 a fp8. Ciò consente di eseguire lo stesso modello con un utilizzo totale della memoria della GPU inferiore, consentendo un parallelismo dei tensori inferiore, che aumenta il throughput.

Le implementazioni della quantizzazione hanno il potenziale di degradare la precisione. Pertanto, abbiamo valutato la precisione per diverse precisioni confrontando la loro statistica di perplexity, una misura di quanto bene l'LLM predice ogni token successivo in una frase, sul corpus WikiText. Per la virgola mobile a 8 bit e il peso a 8 bit con attivazione a 8 bit e SmoothQuant (w8a8 SQ), non vi è stato alcun cambiamento significativo nella perplexity (< 1%) rispetto a fp16 su WikiText, quindi ci siamo sentiti sicuri di procedere. Tuttavia, w4a16 ha mostrato un cambiamento sostanziale del 7% nella perplexity, potenzialmente attribuibile alla precisione ancora inferiore e alle necessarie conversioni dinamiche tra int4 e fp16.

Dimensione del batch

Il parallelismo tramite batching è una strategia classica per spremere le prestazioni da un sistema vincolato dalle risorse. Elaborando più richieste in ogni passaggio in avanti attraverso la rete neurale, è noto che il batching aumenta il throughput a costo di una certa latenza. Il batching comporta anche un consumo di memoria GPU più elevato perché la dimensione della cache KV, che gestisce il meccanismo di attenzione, cresce linearmente con la dimensione del batch.

Nel caso di Llama 2 70B (che ha 80 strati), fp16 con dimensione del batch 32 per una dimensione del contesto di 4096, la dimensione della cache KV arriva a ben 40 GB. Questo finisce per impedire a Llama 2 70B fp16, i cui soli pesi occupano 140 GB, di adattarsi comodamente ai 160 GB di memoria GPU disponibili con parallelismo dei tensori 2 (TP-2).

Risultati

Abbiamo esaminato le combinazioni compatibili delle 4 variabili dell'esperimento e presentiamo di seguito le tendenze più approfondite.

Figura 1 - La latenza delle richieste con diversa dimensione del batch su cinque diverse configurazioni, tutte con parallelismo dei tensori 8, che offre la migliore latenza con 8 GPU disponibili. All'interno di ciascuna configurazione, la latenza generalmente raddoppia quando si aumenta la dimensione del batch da 1 a 32, e raddoppia di nuovo da 32 a 128. Su dimensioni del batch sufficientemente grandi, H100 dimezza approssimativamente la latenza rispetto ad A100. A100 utilizza la precisione mista perché l'architettura manca di supporto nativo per fp8. w8a8 con SmoothQuant (SQ) mira a somigliare a fp8.

Il miglioramento della latenza della quantizzazione è nell'ordine del 10% quando si confrontano H100 fp16 → fp8 e A100 fp16 → w8a8 con SmoothQuant. Tuttavia, la precisione mista w4a16 in realtà funziona meglio con dimensioni del batch ridotte e peggio con dimensioni del batch più elevate rispetto a fp16. Ciò potrebbe essere dovuto a una serie di fattori, inclusi kernel di calcolo meno ottimizzati, tempo di casting tra int4 e fp16 e il fatto che w4a16 utilizza ancora virgole mobili a 16 bit per le attivazioni, con conseguente assenza di risparmi nelle dimensioni della cache KV. Poiché w4a16 ha anche dimostrato una precisione inferiore, concludiamo che dovremmo attenerci a w8a8 SQ per A100 e fp8 per H100.

Figura 2 - Il throughput su configurazioni TP-8 con architettura, quantizzazione e dimensione del batch diverse. Per ogni architettura e quantizzazione, la dimensione del batch è stata scelta come la più grande che rispettasse un requisito di latenza di 25600ms (20 token al secondo per 512 token), in modo da confrontare configurazioni con latenza simile. Con questo requisito, H100 con BS-128 raggiunge il 228% del throughput rispetto ad A100 BS-64 utilizzando la stessa quantizzazione (fp16) e ha persino una latenza di risposta inferiore nonostante il batch raddoppiato. La quantizzazione con fp8 migliora questo fattore al 251%.

Nelle nostre prime due figure, presentiamo solo configurazioni di TP-8. H100 ottiene il 54% della latenza e il 184% del throughput rispetto ad A100 quando entrambi usano fp16 / BS-128 / TP-8, che migliora al 49% della latenza e al 202% del throughput quando si usa fp8 su H100. Questo miglioramento delle prestazioni può essere attribuito agli aumenti della potenza di calcolo e della larghezza di banda della memoria tra H100 e A100. In particolare, la differenza è meno pronunciata con dimensioni del batch inferiori dove l'utilizzo potrebbe essere inferiore.

Mentre costruiamo la nostra piattaforma, vogliamo rispettare determinati requisiti di latenza per i nostri utenti massimizzando al contempo il throughput. Pertanto, piuttosto che confrontare A100 e H100 con la stessa dimensione del batch, ha più senso per noi confrontare il loro throughput solo in configurazioni in cui soddisfano un requisito di latenza. Abbiamo impostato un limite di 25600ms di latenza per il completamento dei 512 token di output e abbiamo riscontrato che H100 / TP-8 / fp8 / BS-128 produce il 251% del throughput rispetto ad A100 / TP-8 / fp16 / BS-64, poiché è in grado di elaborare il doppio della dimensione del batch a una latenza inferiore. Dato che la quantizzazione fornisce risparmi di memoria GPU, ora dobbiamo valutare come il parallelismo dei tensori possa aggiungere un ulteriore livello di ottimizzazione.

Figura 3 - La latenza su diverse dimensioni del batch e parallelismo dei tensori per H100 fp8. La latenza generalmente raddoppia quando si aumenta la dimensione del batch da 1 a 32, e raddoppia di nuovo da 32 a 128. TP-2 è costantemente circa due volte più lento di TP-8 quando le dimensioni del batch sono uguali. Raddoppiare il parallelismo dei tensori mentre si raddoppia la dimensione del batch mantiene la latenza relativamente stabile poiché il numero di batch elaborati per GPU rimane uniforme.

Quando si tratta di quantizzazione e architettura, ci sono chiari vincitori: H100 domina A100 e la quantizzazione a precisione ridotta migliora l'utilizzo della memoria, la latenza e il throughput. Tuttavia, la dimensione del batch e il parallelismo dei tensori presentano un compromesso nelle nostre metriche chiave. Una dimensione del batch maggiore ottimizza il throughput a costo di un aumento della latenza e del consumo di memoria. D'altra parte, un parallelismo dei tensori più elevato aumenta il pool complessivo di memoria disponibile e ottimizza la latenza, ma scambia il throughput a causa dei costi di sincronizzazione della moltiplicazione di matrici distribuita e in virtù del blocco di più risorse GPU.

Figura 4 - Il throughput su diverse dimensioni del batch e parallelismo dei tensori per H100 fp8. Il throughput più elevato deriva da TP-2 BS-128, al 460% rispetto alla base di A100/TP-8/fp16/BS-64. Tuttavia, TP-2 BS-128 è anche il risultato più lento nella Figura 3.

La configurazione che massimizza il throughput del nostro esperimento è H100 / fp8 / TP-2 / BS-128, a 767 token di output al secondo per GPU. Questo è un miglioramento del 460% rispetto ad A100 / fp16 / TP-8 / BS-64. Tuttavia, ha il costo di una latenza raddoppiata - più vicino a 42000ms per 512 token di output - quindi potrebbe non essere adatto come configurazione di produzione. I risultati di TP-4 BS-128 (626 tok/sec/gpu a 26188ms di tempo di risposta) e TP-2 BS-32 (435 tok/sec/gpu a 18821ms di tempo di risposta) potrebbero rappresentare compromessi migliori sulle nostre metriche chiave.

Conclusione

I nostri risultati dimostrano che:

Raggiungiamo il 54% della latenza e il 184% del throughput utilizzando H100 rispetto ad A100 data la stessa configurazione, che migliora rispettivamente al 49% e al 202% quando H100 sfrutta il suo supporto nativo per fp8.

Quando si massimizza il throughput soggetto a un vincolo di latenza, H100 / fp8 / TP-8 / BS-128 produce il 251% del throughput rispetto ad A100 / fp16 / TP-8 / BS-64, poiché può elaborare il doppio del batch a una velocità maggiore.

Sfruttando H100 con TP-2 con fp8, possiamo ottenere il 373% del throughput di A100 / fp16 / TP-8 / BS-128, con un aumento della latenza inferiore al 10%.

La dimensione del batch e il parallelismo dei tensori presentano un compromesso tra throughput e latenza per l'operatore di un sistema di inferenza LLM.

Questi risultati ci rendono fiduciosi riguardo a una transizione completa alle GPU H100 nel nostro stack hardware precedentemente alimentato da A100. Siamo entusiasti di poter confermare i guadagni di prestazioni pubblicizzati da NVIDIA e attendiamo con impazienza le loro prossime innovazioni nell'hardware accelerato.

Cosa c'è dopo

La nostra prossima frontiera per l'ottimizzazione è esaminare l'impatto sulla precisione e sulle prestazioni della struttura sparsa e della precisione int4, che potrebbero ridurre significativamente l'impronta di memoria GPU di Llama 2 70B e produrre miglioramenti fino a 2x nella latenza. Siamo entusiasti di continuare il viaggio dell'inferenza velocissima e speriamo di consentire ai nostri utenti di creare potenti applicazioni sulla nostra piattaforma.

A breve termine, pplx-api eliminerà i limiti di velocità e offrirà più LLM Perplexity personalizzati, incluso un LLM basato su Internet con messa a terra per i fatti.

Registrati a Perplexity Pro su perplexity.ai/pro. Ottieni l'accesso alla nostra pplx-api all'avanguardia e sfrutta queste funzionalità avanzate nei tuoi progetti. Scopri di più su pplx-api nel nostro blog.

Ti interessa plasmare il futuro dell'IA? Stiamo assumendo! Entra a far parte di un team che guida l'infrastruttura LLM generativa su scala massiccia. Esplora le opportunità su Perplexity Careers.

Autori:

Aarash Heydari, Grigorii Alekseev, Kevin Hu, Denis Yarats