Come abbiamo creato i modelli di linguaggio di nuova generazione di DeepL usando FP8 per l'addestramento e l'inferenza

Indice dei contenuti
- Qual è la differenza tra i formati BF16 e FP8?
- Pre-addestramento per i modelli di linguaggio large DeepL
- Usa il formato FP8 per l'addestramento a precisione mista
- FP8 contro BF16 per le prestazioni di addestramento
- FP8 contro BF16 per la qualità dell'addestramento LLM
- Qualità dell'addestramento a valle FP8 vs BF16
- Dall'addestramento FP8 all'inferenza
- I vantaggi di FP8 per l'inferenza
- A proposito degli autori
Quando DeepL ha distribuito il nostro attuale NVIDIA DGX SuperPOD con 544 GPU NVIDIA H100 Tensor Core, non abbiamo solo avuto un bel salto nella potenza di calcolo. L'H100 introduce anche il supporto nativo per i tipi di dati a virgola mobile a 8 bit (FP8), grazie a una nuova generazione di Tensor Core, che permettono alla GPU di fare moltiplicazioni matriciali e altre operazioni tensoriali con precisione FP8. Calcolando le moltiplicazioni matriciali in FP8, possiamo migliorare la velocità di elaborazione quando addestriamo e distribuiamo i nostri modelli linguistici di grandi dimensioni (LLM), dato che la maggior parte dei calcoli nei moderni LLM sono proprio moltiplicazioni matriciali.
Passare da calcoli a 16 bit a quelli a 8 bit ha fatto un bel salto nello sviluppo dei modelli linguistici di nuova generazione di DeepL. Ci permette di creare modelli linguistici molto più grandi, con un sacco più di parametri che migliorano parecchio la qualità secondo gli esperti di lingue, ma sempre con la stessa finestra di latenza per l'inferenza di produzione. Questo vuol dire che le traduzioni sono 1,4 volte migliori rispetto ai nostri modelli precedenti per le lingue europee e 1,7 volte migliori per le coppie di lingue più complicate, tipo inglese e giapponese, ma danno risultati altrettanto veloci. Questo vuol dire anche che i nostri modelli possono gestire un sacco di richieste su più funzioni e funzioni, senza rovinare l'esperienza utente.
In altre parole, l'addestramento e l'inferenza FP8 hanno avuto un ruolo fondamentale nel potenziare l'IA linguistica di DeepL.
In questo post vogliamo spiegare il percorso che abbiamo fatto per usare FP8 per l'addestramento e l'inferenza, condividere alcuni degli strumenti e delle tecniche che ci hanno aiutato a raggiungere questo successo e darvi un'idea dei risultati che abbiamo ottenuto in termini di prestazioni di addestramento e inferenza lungo il percorso.
Qual è la differenza tra i formati BF16 e FP8?
La spiegazione semplice della differenza tra BFloat16 (BF16) e FP8 è che quest'ultimo usa la metà dei bit per esprimere i valori. In pratica, BF16 usa le 16 posizioni disponibili in due byte da 8 bit ciascuno. FP8 usa solo un byte.
Il numero di bit che hai a disposizione determina quanto puoi essere preciso quando distribuisci la mantissa e l'esponente dei numeri in virgola mobile in notazione scientifica. BF16 ha 1 bit di segno, 8 bit per l'esponente e 7 bit per la mantissa. FP8 ha la metà dei bit da usare, con 1 bit di segno e 7 bit divisi tra esponente e mantissa. Per questo motivo, ha una portata più ridotta e una precisione inferiore rispetto al BF16. Può rappresentare un intervallo più ristretto e un numero minore di valori all'interno di tale intervallo.
Per esempio, diciamo che vogliamo mostrare l'età della Terra in miliardi di anni (circa 4,543). In BF16, possiamo rappresentarlo esattamente come 0100000010010001.
Che ne dici di rappresentare quel numero in FP8? In realtà ci sono due formati FP8 tra cui scegliere: E4M3 ed E5M2. Le lettere e i numeri qui indicano come i bit sono divisi tra l'esponente (E) e la mantissa (M). Più bit usi per l'esponente, più grande sarà il range di numeri che puoi descrivere, e più bit usi per la mantissa, più numeri potrai descrivere all'interno di quel range.
Qualunque formato FP8 tu scelga, non è davvero possibile rappresentare 4,543 in modo preciso. Se scegli E4M3, che è un po' più preciso, puoi avvicinarti di più (4,5). In E5M2, il massimo che puoi ottenere è 5.
D'altra parte, nonostante questa mancanza di gamma e precisione, FP8 permette calcoli più veloci e richiede una quantità di memoria notevolmente inferiore rispetto a BF16. Questo è super utile per l'inferenza e, con l'approccio giusto, può essere super utile anche per accelerare l'addestramento. Il punto è: quanto devono essere ampi e precisi l'addestramento e la precisione dell'LLM? Hai bisogno di dire con precisione quanti anni ha la Terra? O forse avvicinarsi a 43 milioni di anni è abbastanza vicino? Se ti interessa l'universo in generale, probabilmente ti basterà quel secondo livello di precisione. L'errore di arrotondamento rappresenta solo circa lo 0,3% dell'età dell'universo, dopotutto.
Il percorso di DeepL dimostra che FP8 può dare quello che serve per un training LLM di alta qualità, e questo ha aperto nuove possibilità per quello che insegniamo ai nostri modelli e per come li distribuiamo nella pratica.
Pre-addestramento per i modelli di linguaggio large DeepL
Il percorso che intraprendiamo con la formazione e l'inferenza FP8 inizia con il pre-addestramento dei nostri LLM. Dopo la fase di pre-addestramento, perfezioniamo i nostri modelli su determinati compiti, riduciamo i modelli di grandi dimensioni in modelli più piccoli, facciamo apprendimento rinforzato e distribuiamo una serie di strategie di parallelizzazione in modo da poter sfruttare l'enorme numero di GPU di cui disponiamo.
Usa il formato FP8 per l'addestramento a precisione mista
Abbiamo cambiato il nostro codice di addestramento da BF16 a FP8 usando NVIDIA Transformer Engine: una libreria di addestramento di NVIDIA che rende più veloci i modelli transformer e include supporto per FP8. Transformer Engine offre componenti essenziali che rendono più facile l'addestramento a precisione mista, gestendo senza problemi la conversione tra i formati FP8 e BF16 e occupandosi dei fattori di scala.
Usiamo le impostazioni predefinite del Transformer Engine, come suggerito da NVIDIA, usando E4M3 nel passaggio in avanti per l'addestramento e poi E5M2 nel passaggio all'indietro. Questo vuol dire che stiamo usando il formato con maggiore precisione per prevedere la distribuzione di probabilità del token successivo, e poi il formato con minore precisione, ma con un intervallo maggiore, per calcolare i gradienti necessari per aggiornare il modello, quando la precisione è meno importante. Usiamo ciascuno dei due formati per il compito a cui è più adatto.
Nel grafico qui sotto, abbiamo messo tutti i numeri che si possono rappresentare con il formato E4M3. Come puoi vedere, questi numeri sono quasi tutti intorno allo zero, con un massimo di meno di 500. In realtà, i valori che si possono rappresentare nei formati FP8 si possono mettere in una tabella super breve. Il trucco per far funzionare questo formato nell'allenamento è capire come sono distribuiti quei valori e lavorare su questo.
Questo significa che bisogna salvare dei fattori di scala extra insieme ai tensori di peso FP8 per risolvere il problema della gamma limitata e evitare che si verifichino overflow e underflow. Quando fai calcoli con i tuoi tensori a bassa precisione, devi anche considerare i fattori di scala. Per esempio, quando moltiplichi due tensori, usi la formula: (A_fp8 * A_scale) x (B_fp8 * B_scale), dove A_fp8 e B_fp8 sono tensori a 8 bit e le scale sono scalari a 32 bit. C'è un supporto hardware specifico per queste operazioni.

FP8 contro BF16 per le prestazioni di addestramento
Quando parliamo di prestazioni di addestramento, ci riferiamo a quanto velocemente un modello può essere addestrato con la potenza di calcolo che ha a disposizione. Per vedere come va l'addestramento tra FP8 e BF16, diamo un'occhiata all'utilizzo dei FLOPS del modello (MFU), cioè il numero di operazioni in virgola mobile al secondo (FLOPS) che il modello fa, come percentuale dei FLOPS che si possono fare tecnicamente con l'hardware che hai a disposizione.
Per il nostro confronto, abbiamo usato il numero di FLOPS che si possono fare con il formato BF16 come punto di riferimento, anche se, tecnicamente, si possono fare più FLOPS passando a FP8. Questo ci ha permesso di misurare il guadagno incrementale nell'uso della potenza di elaborazione disponibile che diventa possibile quando si passa da BF16 a FP8.
Come puoi vedere nel grafico qui sotto, l'efficienza con cui il nostro modello di addestramento usa la potenza di calcolo disponibile è passata dal 44,6% MFU al 67% MFU con FP8, accelerando di fatto il nostro modello di addestramento del 50%.

È un bel salto di qualità, di per sé. Per farlo, abbiamo collaborato con NVIDIA per ottimizzare il nostro uso delle funzioni di Transformer Engine. Grazie a un altro programma di allenamento, siamo riusciti ad aumentare gradualmente le prestazioni del 25% in 15 mesi, arrivando all'80% di MFU.

FP8 contro BF16 per la qualità dell'addestramento LLM
I miglioramenti dell'FP8 in termini di prestazioni di formazione sono davvero notevoli. Comunque, quello che ci interessa davvero in DeepL è la qualità dell'addestramento. Come si confronta questo con la qualità dell'allenamento con precisione BF16?
Per vedere come va la qualità di FP8, abbiamo provato ad addestrare uno dei nostri modelli in entrambi i formati. Questo ci ha permesso di confrontare le perdite di formazione e la qualità a valle.
Abbiamo addestrato un modello da 1,5 miliardi su tre trilioni di token e poi abbiamo confrontato la qualità dell'addestramento FP8 rispetto a BF16. La misura chiave in questo caso era la perdita di addestramento, che si riferisce alla capacità del modello di prevedere il token successivo.
Come puoi vedere dal grafico qui sotto, abbiamo notato che BF16 è un po' meglio di FP8, visto che la linea di FP8 è appena sopra quella di BF16. Comunque, questa differenza viene messa in secondo piano dalle fluttuazioni molto più ampie nella perdita di addestramento da un passo all'altro che si verificano per entrambi i formati e, in entrambi i casi, vediamo lo stesso miglioramento tangibile nella riduzione della perdita di addestramento nel tempo.

Qualità dell'addestramento a valle FP8 vs BF16
Poi abbiamo provato la qualità che l'addestramento in FP8 e BF16 ha dato in un'applicazione pratica a valle.
In questo caso, abbiamo provato come il modello si comportava quando lavorava con l'inglese e il tedesco. Abbiamo confrontato la perplessità di validazione, che misura quanto un modello è incerto quando deve prevedere il prossimo token in una sequenza. Ancora una volta, si pensa che la confusione diminuirà col tempo. In questo scenario pratico, non abbiamo notato alcun calo di qualità con l'addestramento FP8 rispetto al BF16.

Il risultato finale del passaggio da BF16 a FP8 è che possiamo addestrare i nostri modelli più velocemente, usando meno memoria, e ottenere la stessa qualità di addestramento, con solo un piccolo calo in termini di perdita di addestramento e una complessità di convalida simile. Questo vuol dire che DeepL riesce a creare modelli più sofisticati, affrontando compiti più complessi, sfruttando al massimo la potenza di elaborazione. Questo allarga un sacco le possibilità di cosa possiamo fare con l'addestramento LLM.
Dall'addestramento FP8 all'inferenza
Il prossimo passo è preparare gli LLM per l'inferenza in produzione. Qui il grosso del lavoro di supporto è fatto da NVIDIA TensorRT-LLM, che è la soluzione di NVIDIA per l'inferenza LLM scalabile e che supporta FP8. Prende i pesi del tuo modello dall'addestramento e crea un motore per ottimizzare le operazioni del modello in modo che sia il più efficiente possibile dal punto di vista computazionale, usando tecniche di ottimizzazione come la fusione dei kernel, il codice C++/CUDA ottimizzato, il caching KV e il batching continuo in volo.
I vantaggi di FP8 per l'inferenza
L'inferenza per gli LLM ha sempre a che fare con l'interazione tra throughput (il numero di token che si possono elaborare in un certo periodo di tempo) e latenza. È ovvio che per dare la migliore esperienza possibile ai clienti bisogna tenere sotto controllo la latenza. Comunque, anche la velocità di elaborazione è super importante per DeepL perché determina quante richieste possiamo gestire in un dato momento e quindi quanto può fare il nostro modello nella pratica.
È normale che, quando la velocità aumenta, anche la latenza tenda a salire. Mettere insieme più richieste insieme fa sì che si riesca a fare più cose, ma per ogni utente singolo ci mette più tempo. Questo potrebbe influire sull'esperienza del cliente. Comunque, le prestazioni di inferenza di FP8 rispetto a BF16 modificano parecchio questo equilibrio a nostro favore.
Come puoi vedere dal grafico qui sotto, per la maggior parte delle dimensioni dei batch, FP8 riesce a gestire il doppio della velocità di elaborazione rispetto a BF16 con lo stesso livello di latenza. Se impostiamo un budget di latenza specifico che garantisca un'esperienza ottimale per i nostri utenti, possiamo verificarlo nella pratica. In pratica, FP8 ha praticamente raddoppiato la capacità effettiva dei nostri LLM in termini di velocità di elaborazione.

In altre parole, il passaggio da BF16 a FP8 non ci ha solo permesso di creare modelli di linguaggio più potenti e sofisticati per DeepL. Ciò garantisce anche che siamo in grado di applicare efficacemente tali LLM, per offrire esperienze ottimali ai clienti e ampliare l'impatto della nostra IA linguistica nel mondo reale. Otteniamo un addestramento più veloce di modelli più grandi, che possono poi funzionare con gli stessi parametri di latenza, gestendo il doppio delle richieste.
E ora? Abbiamo appena distribuito il nuovo NVIDIA DGX SuperPOD con i sistemi NVIDIA DGX GB200, che ci dà un altro aumento quasi esponenziale della potenza di calcolo. Quello che ci interessa di più è che questa macchina porterà una nuova generazione di Tensor Core che possono supportare in modo nativo operazioni tensoriali FP4 come le moltiplicazioni matriciali. È allora che il nostro viaggio ricomincia. È stato davvero interessante vedere cosa si può fare con un solo byte quando si parla di formazione e inferenza. Dai un'occhiata qui per vedere cosa si può fare con mezzo byte.
A proposito degli autori
Markus Schnös, Staff Research HPC Engineer
Markus Schnös lavora come ingegnere di ricerca HPC presso DeepL, dove si occupa di scalare l'addestramento e l'inferenza LLM. Ha un interesse particolare per l'addestramento distribuito e il calcolo in virgola mobile a bassa precisione.
www.linkedin.com/in/markus-schnoes-349300185
Fabian Joswig, Staff Research HPC Engineer
Fabian Joswig è un ingegnere ricercatore presso DeepL, con esperienza nel machine learning, nel calcolo ad alte prestazioni e nella fisica teorica delle particelle. Si occupa di far crescere i modelli e le infrastrutture di IA per il traduttore più preciso al mondo.