mozzicone Accelerare l'inferenza di modelli linguistici di grandi dimensioni: tecniche per una distribuzione efficiente - Unite.AI
Seguici sui social

Ingegneria rapida

Accelerare l'inferenza di modelli linguistici di grandi dimensioni: tecniche per una distribuzione efficiente

mm

Pubblicato il

 on

Accelerazione dell'inferenza LLM

Modelli linguistici di grandi dimensioni (LLM) come GPT-4, Lamae PaLM stanno ampliando i confini di ciò che è possibile fare con l'elaborazione del linguaggio naturale. Tuttavia, l’implementazione di questi enormi modelli negli ambienti di produzione presenta sfide significative in termini di requisiti computazionali, utilizzo della memoria, latenza e costi. Poiché gli LLM continuano a diventare più grandi e più capaci, l'ottimizzazione delle prestazioni di inferenza è fondamentale per le applicazioni del mondo reale.

In questo approfondimento tecnico, esploreremo tecniche all'avanguardia per accelerare l'inferenza LLM, consentendo tempi di risposta più rapidi, throughput più elevato e utilizzo più efficiente delle risorse hardware. Tratteremo metodi che vanno dalle tecniche di precisione numerica e nuovi meccanismi di attenzione alle innovazioni architettoniche adattate esplicitamente per una generazione efficiente di testo.

Iniziamo comprendendo perché l'inferenza LLM è così impegnativa rispetto ai tradizionali modelli PNL.

La sfida dell'inferenza con modelli linguistici di grandi dimensioni

Prima dell’avvento dei LLM, l’elaborazione del linguaggio naturale si basava su modelli più piccoli focalizzati su attività specifiche come la classificazione del testo, il riconoscimento delle entità denominate e l’analisi del sentiment. Sebbene siano ancora intensivi dal punto di vista computazionale, questi modelli potrebbero essere implementati su hardware modesto e seguire processi di inferenza relativamente semplici.

Gli LLM, d’altro canto, rappresentano un cambiamento di paradigma. Questi modelli vengono addestrati su vasti set di dati utilizzando miliardi di parametri, consentendo loro di eseguire un’ampia gamma di compiti linguistici con notevole competenza. Tuttavia, questa potenza ha un costo: le richieste computazionali aumentano notevolmente sia durante l’addestramento che durante l’inferenza.

Una sfida chiave è la natura autoregressiva della generazione di testo con LLM. Per produrre testo simile a quello umano, questi modelli prevedono un token (parola o sottoparola) alla volta, con ogni nuovo token che dipende dall'output generato in precedenza. Questa dipendenza sequenziale impedisce una parallelizzazione efficiente e si traduce in requisiti computazionali che si adattano polinomialmente con la lunghezza della sequenza.

Inoltre, i LLM spesso richiedono lunghe sequenze di input (prompt) per stabilire il contesto necessario per la generazione di testo di alta qualità. Lunghezze di input più lunghe richiedono più memoria per memorizzare stati intermedi e matrici di attenzione, mettendo a dura prova le risorse hardware.

Di fronte a queste sfide uniche, le tecniche di ottimizzazione tradizionali come la quantizzazione e i grafici di calcolo statico possono non essere all’altezza, faticando a mantenere le prestazioni LLM garantendo al tempo stesso accelerazioni significative. Analizziamo alcune delle strategie chiave studiate appositamente per accelerare l'inferenza LLM.

Tecniche di precisione numerica

Dalla precisione da 32 bit a 16 bit

Dalla precisione da 32 bit a 16 bit

Una strada per accelerare LLM l'inferenza consiste nel sfruttare una precisione numerica ridotta per i pesi e le attivazioni del modello. I moderni framework di deep learning come PyTorch e TensorFlow utilizzano in genere una precisione a virgola mobile a 32 bit (FP32) per impostazione predefinita. Tuttavia, la ricerca ha dimostrato che gli LLM possono spesso mantenere un'elevata precisione anche quando funzionano con precisione inferiore, come numeri interi a 16 bit (FP16), interi a 8 bit (INT8) o anche interi a 4 bit (INT4).

La riduzione della precisione numerica offre numerosi vantaggi:

  • Impronta di memoria ridotta: le rappresentazioni a precisione inferiore richiedono meno memoria, consentendo a modelli più grandi o dimensioni batch di adattarsi agli stessi vincoli hardware.
  • Calcolo più veloce: Molte CPU e GPU moderne forniscono istruzioni specializzate e accelerazione hardware per operazioni aritmetiche di precisione inferiore, consentendo accelerazioni significative.
  • Migliore efficienza energetica: Con requisiti di memoria inferiori e calcoli più rapidi, l'inferenza con precisione inferiore può tradursi in un consumo energetico ridotto, un vantaggio cruciale per le implementazioni edge e mobili.

Sebbene potenti, le tecniche di precisione numerica introducono una certa perdita di precisione rispetto al funzionamento FP32. La chiave è valutare attentamente questo compromesso tra guadagni computazionali e potenziale degrado delle prestazioni per il tuo caso d'uso specifico.

Esistono due approcci principali alla quantizzazione con gli LLM:

Quantizzazione post-allenamento (PTQ): In questo metodo, un LLM viene prima addestrato utilizzando la precisione FP32 standard. Dopo l'addestramento, i pesi del modello vengono quantizzati (convertiti) in un formato di precisione inferiore come INT8 o INT4. Il PTQ è semplice da implementare ma può portare a maggiori cali di precisione.

Formazione consapevole della quantizzazione (QAT): Con QAT il processo di quantizzazione viene simulato durante la fase di training stessa. Ciò consente al modello di imparare a compensare gli errori di quantizzazione, riducendo al minimo il degrado della precisione quando viene distribuito il modello quantizzato finale. Il QAT è più complesso ma spesso produce risultati migliori rispetto al PTQ.

Per l'applicazione pratica, si potrebbero sfruttare i modelli prequantizzati disponibili su piattaforme come Abbracciare il viso, che ospita una varietà di modelli ottimizzati attraverso diversi metodi di quantizzazione. Ad esempio, se si desidera un modello quantizzato utilizzando Auto-GPTQ, gli utenti possono caricarlo facilmente utilizzando la libreria di trasformatori di Hugging Face. Inoltre, per quantizzare un modello, è possibile utilizzare strumenti come AutoGPTQ, che si integrano perfettamente con le librerie esistenti per comprimere il modello in modo efficiente.

Ecco un esempio di caricamento di un modello Llama-2-7b prequantizzato utilizzando la libreria di trasformatori Hugging Face:

from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "TheBloke/Llama-2-7b-Chat-GPTQ"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id)
And for custom quantization, one might follow these steps using the AutoGPTQ toolkit:
from transformers import AutoModelForCausalLM, AutoTokenizer, GPTQConfig
model_id = "llama-2-7b-original"
tokenizer = AutoTokenizer.from_pretrained(model_id)
quantization_config = GPTQConfig(bits=4, dataset="your-dataset", tokenizer=tokenizer)
model = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=quantization_config)

Ricordare che la quantizzazione potrebbe richiedere una messa a punto post-quantizzazione o un'ingegneria tempestiva per mantenere la qualità del modello. Per una nuova quantizzazione, puoi contribuire alla comunità spingendo i tuoi modelli quantizzati su piattaforme come Hugging Face.

Assicurati sempre di trovare un equilibrio tra dimensioni del modello, requisiti computazionali e prestazioni quando selezioni la strategia di quantizzazione per il tuo caso d'uso specifico.

 

L'algoritmo di attenzione Flash

Il meccanismo di attenzione multi-testa è una componente fondamentale degli LLM basati su trasformatore, consentendo al modello di catturare dipendenze a lungo raggio e rappresentazioni contestualizzate. Tuttavia, questa operazione di attenzione è computazionalmente inefficiente per la generazione di testo autoregressivo, poiché richiede il ricalcolo di molti degli stessi valori per ogni nuovo token.

I Algoritmo di attenzione flash, introdotto nel documento FlashAttention, fornisce un approccio più efficiente in termini di memoria e più facile da parallelizzare per l'operazione di attenzione. Invece di ricalcolare i valori di attenzione per ciascun token, Flash Attention memorizza nella cache e riutilizza matrici chiave/valore intermedie, evitando calcoli ridondanti.

Questa ottimizzazione non solo riduce il sovraccarico computazionale, ma migliora anche i modelli di accesso alla memoria, portando a un migliore utilizzo della larghezza di banda e del parallelismo della memoria della GPU.

Sebbene i dettagli di Flash Attention siano piuttosto complessi, l'idea di alto livello è quella di scomporre l'operazione di attenzione in due fasi:

  1. Incorporamento somma prefisso: questa fase calcola e memorizza nella cache gli incorporamenti di chiave/valore per tutti i token di input, consentendo un riutilizzo efficiente durante la generazione.
  2. Attenzione causale: l'operazione di attenzione vera e propria, ora ottimizzata per sfruttare gli incorporamenti di chiave/valore memorizzati nella cache sin dalla prima fase.

Separando queste fasi, Flash Attention può trarre vantaggio dalle operazioni GPU altamente parallele, accelerando significativamente il collo di bottiglia dell'attenzione nell'inferenza LLM.

Ecco una breve illustrazione concettuale dell'implementazione di Flash Attention con un LLM:

from transformers import AutoModelForCausalLM
import torch
from flash_attention import flash_attention
# Load an LLM like OctoCoder
model = AutoModelForCausalLM.from_pretrained("bigcode/octocoder")
# Sample system prompt that guides the model towards being a better coding assistant
system_prompt = """... (system prompt details) ..."""
# Preparing a longer input with the system prompt
long_prompt = system_prompt + "Question: Please write a function in Python that transforms bytes to Gigabytes."
# Converting the model for Flash Attention optimization
model.to_bettertransformer()
# Running the model with Flash Attention
start_time = time.time()
with torch.backends.cuda.sdp_kernel(enable_flash=True):
result = model.generate(long_prompt, max_new_tokens=60)
print(f"Generated in {time.time() - start_time} seconds.")

Sebbene Flash Attention offra notevoli miglioramenti in termini di prestazioni, funziona all'interno dell'architettura del trasformatore esistente. Per sfruttare appieno il potenziale dell'inferenza LLM accelerata, dobbiamo esplorare innovazioni architetturali su misura per questo compito.

LLM di potatura

L'eliminazione degli LLM è una tecnica per ridurre le dimensioni del modello mantenendo la funzionalità. Utilizza uno stimatore dipendente dai dati per l'importanza del peso basato su approssimazioni della matrice Hessiana. Nella potatura vengono rimossi i gruppi di peso meno importanti, quindi il modello viene messo a punto per recuperare la precisione. Il pacchetto LLM-Pruner offre script per la potatura con varie strategie supportate. La potatura include la scoperta delle dipendenze, la stima dei contributi del gruppo e una fase di recupero che prevede una breve post-formazione.

Ecco un esempio di codice Python semplificato che dimostra l'uso di LLM-Potatore per un modello LLaMa:

from transformers import AutoModelForSequenceClassification
from pruning import LLMPruner
# Load pre-trained LLaMa model
model = AutoModelForSequenceClassification.from_pretrained("llama-base")
# Initialize the pruner with desired configuration
pruner = LLMPruner(
model,
pruning_ratio=0.25,
block_mlp_layers=(4, 30),
block_attention_layers=(4, 30),
pruner_type='taylor'
)
# Execute pruning
pruned_model = pruner.prune()
# Fine-tune the pruned model
pruned_model.fine_tune(training_data)

Questo schizzo di codice rappresenta il caricamento di un modello LLaMa pre-addestrato, l'impostazione del potatore con configurazioni specifiche (come quali strati sfoltire e il tipo di potatore), l'esecuzione del processo di potatura e, infine, la messa a punto del modello sfoltito.

Tieni presente che per un'implementazione effettiva, dovresti inserire dettagli come il nome del modello specifico, i percorsi dei dati e parametri aggiuntivi per il processo di messa a punto. Inoltre, tieni presente che questo codice è una rappresentazione concettuale e la sintassi effettiva può variare a seconda della libreria e delle versioni utilizzate.

Innovazioni architettoniche per una generazione efficiente di testo

L'architettura del trasformatore, sebbene altamente efficace per le attività di modellazione del linguaggio, è stata progettata come un modello sequenza per sequenza per scopi generali. Quando si distribuiscono LLM per attività di generazione di testo con contesti di input lunghi, i ricercatori hanno scoperto che architetture più specializzate possono migliorare significativamente l'efficienza dell'inferenza senza sacrificare la qualità.

Ecco alcune delle principali innovazioni architetturali che consentono un'inferenza LLM più rapida:

Alibi: L'architettura Alibi, introdotta nel documento PAL-Instruction, separa la modellazione del lungo contesto di input dal processo di generazione del testo stesso. Utilizza una rappresentazione compressa del contesto di input (l'"alibi") per inizializzare il processo di generazione, evitando la necessità di elaborare ripetutamente l'intera sequenza di input durante la generazione autoregressiva.

Incorporamenti Rotary: Invece di utilizzare incorporamenti posizionali standard, la tecnica di incorporamento rotante impiega matrici di rotazione per codificare le informazioni posizionali in modo più efficiente. È stato dimostrato che questo approccio migliora le prestazioni e consente l'elaborazione di sequenze di input più lunghe.

Attenzione multi-query (MQA): Nell'attenzione tradizionale, ogni token di output si occupa dell'intera sequenza di input, risultando in calcoli ridondanti. MQA riformula l'operazione di attenzione per condividere i calcoli su più token di output, riducendo la complessità complessiva.

Attenzione multiquery

Attenzione multiquery

Attenzione alle query raggruppate (GQA): basandosi su MQA, GQA raggruppa i token di output in cluster e calcola l'attenzione congiuntamente per ciascun cluster. Questo approccio riduce ulteriormente i requisiti computazionali mantenendo la generazione di testo di alta qualità.

Pur essendo ancora in fase attiva di ricerca e sviluppo, queste innovazioni architetturali hanno dimostrato notevoli accelerazioni per le attività di inferenza LLM, soprattutto se combinate con tecniche come Flash Attention e ottimizzazione della precisione numerica.

Considerazioni sulla distribuzione nel mondo reale

Oltre agli algoritmi e alle architetture principali, ci sono diverse considerazioni pratiche e compromessi da considerare quando si distribuiscono LLM in ambienti di produzione:

Accelerazione hardware: mentre le CPU possono gestire l'inferenza LLM, le GPU e altri acceleratori come i TPU di Google sono essenziali per ottenere un throughput elevato e una bassa latenza. Scegliere l'hardware giusto e ottimizzare l'utilizzo della memoria è fondamentale.

Batch e parallelismo: per sfruttare appieno il parallelismo hardware, strategie come l'inferenza batch (elaborazione di più input contemporaneamente) e il parallelismo del modello (distribuzione di un LLM su più dispositivi) possono aumentare significativamente la produttività.

Quantizzazione vs. compromesso di qualità: il grado di quantizzazione (8 bit, 4 bit, ecc.) avrà un impatto diretto sulla velocità di inferenza e sull'utilizzo della memoria, ma influirà anche sulla qualità dell'output. Questo compromesso deve essere valutato attentamente per ciascun caso d'uso.

Distillazione del modello: Un'alternativa alla quantizzazione, le tecniche di distillazione del modello possono comprimere LLM di grandi dimensioni in modelli studenteschi più piccoli ed efficienti mantenendo un'elevata precisione.

Caching e runtime ottimizzati: runtime di deep learning ottimizzati come TensorRT di NVIDIA e framework progettati per il servizio LLM (ad esempio, Composable Inference Suite di MosaicML) possono fornire miglioramenti significativi delle prestazioni attraverso tecniche come la fusione degli operatori, l'ottimizzazione del kernel e strategie di caching intelligenti.

Il percorso verso un'implementazione LLM ottimale spesso comporta la combinazione di più tecniche considerando attentamente i requisiti specifici dell'applicazione, i vincoli dell'infrastruttura e gli obiettivi prestazionali.

Conclusione

Poiché i modelli linguistici di grandi dimensioni continuano la loro rapida evoluzione, accelerare le loro prestazioni di inferenza sta diventando sempre più cruciale per consentire applicazioni del mondo reale e democratizzare l’accesso a queste potenti funzionalità di intelligenza artificiale.

In questa guida tecnica, abbiamo esplorato tecniche all'avanguardia che spaziano dall'ottimizzazione della precisione numerica, a nuovi algoritmi di attenzione come Flash Attention e innovazioni architettoniche su misura per una generazione efficiente di testo. Sebbene ciascun approccio offra i propri vantaggi, il vero potere spesso risiede nel combinare più strategie mentre si affrontano gli intricati compromessi tra velocità, utilizzo della memoria e qualità dell'output.

Guardando al futuro, possiamo aspettarci una ricerca e uno sviluppo continui in questo settore, alimentati dall’insaziabile domanda di LLM più capaci e accessibili. Dall'accelerazione hardware e compressione dei modelli ad architetture completamente nuove, la ricerca di un'inferenza LLM efficiente rimane una frontiera entusiasmante nel mondo dell'elaborazione del linguaggio naturale e dell'intelligenza artificiale.

Ho trascorso gli ultimi cinque anni immergendomi nell'affascinante mondo del Machine Learning e del Deep Learning. La mia passione e competenza mi hanno portato a contribuire a oltre 50 diversi progetti di ingegneria del software, con un focus particolare su AI/ML. La mia continua curiosità mi ha anche attirato verso l'elaborazione del linguaggio naturale, un campo che non vedo l'ora di esplorare ulteriormente.