Confronta e ottimizza la distribuzione degli endpoint in Amazon SageMaker JumpStart | Servizi Web di Amazon

Confronta e ottimizza la distribuzione degli endpoint in Amazon SageMaker JumpStart | Servizi Web di Amazon

Quando distribuiscono un modello linguistico di grandi dimensioni (LLM), i professionisti dell'apprendimento automatico (ML) in genere si preoccupano di due misurazioni per le prestazioni del servizio del modello: latenza, definita dal tempo necessario per generare un singolo token, e velocità effettiva, definita dal numero di token generati al secondo. Anche se una singola richiesta all'endpoint distribuito mostrerebbe una velocità effettiva approssimativamente uguale all'inverso della latenza del modello, questo non è necessariamente il caso quando più richieste simultanee vengono inviate simultaneamente all'endpoint. A causa delle tecniche di servizio dei modelli, come l'invio in batch continuo di richieste simultanee lato client, latenza e velocità effettiva hanno una relazione complessa che varia in modo significativo in base all'architettura del modello, alle configurazioni di servizio, all'hardware del tipo di istanza, al numero di richieste simultanee e alle variazioni nei payload di input come come numero di token di input e token di output.

Questo post esplora queste relazioni tramite un'analisi comparativa completa dei LLM disponibili in Amazon SageMaker JumpStart, comprese le varianti Llama 2, Falcon e Mistral. Con SageMaker JumpStart, i professionisti del machine learning possono scegliere tra un'ampia selezione di modelli di base disponibili pubblicamente da distribuire a utenti dedicati Amazon Sage Maker istanze all'interno di un ambiente isolato dalla rete. Forniamo principi teorici su come le specifiche dell'acceleratore influiscono sul benchmarking LLM. Dimostriamo inoltre l'impatto della distribuzione di più istanze dietro un singolo endpoint. Infine, forniamo consigli pratici per personalizzare il processo di distribuzione SageMaker JumpStart per allinearlo ai tuoi requisiti di latenza, throughput, costi e vincoli sui tipi di istanze disponibili. Tutti i risultati del benchmarking e le raccomandazioni si basano su un approccio versatile taccuino che puoi adattare al tuo caso d'uso.

Benchmarking degli endpoint distribuito

La figura seguente mostra i valori di latenza più bassa (a sinistra) e di throughput più elevato (a destra) per le configurazioni di distribuzione in una varietà di tipi di modelli e tipi di istanze. È importante sottolineare che ciascuna di queste distribuzioni di modelli utilizza le configurazioni predefinite fornite da SageMaker JumpStart in base all'ID del modello e al tipo di istanza desiderati per la distribuzione.

Confronta e ottimizza la distribuzione degli endpoint in Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Ricerca verticale. Ai.

Questi valori di latenza e throughput corrispondono a payload con 256 token di input e 256 token di output. La configurazione con la latenza più bassa limita il modello servito a una singola richiesta simultanea, mentre la configurazione con velocità effettiva più alta massimizza il numero possibile di richieste simultanee. Come possiamo vedere nel nostro benchmarking, l'aumento delle richieste simultanee aumenta in modo monotono il throughput con miglioramenti decrescenti per richieste simultanee di grandi dimensioni. Inoltre, i modelli vengono completamente suddivisi in partizioni sull'istanza supportata. Ad esempio, poiché l'istanza ml.g5.48xlarge ha 8 GPU, tutti i modelli SageMaker JumpStart che utilizzano questa istanza vengono partizionati utilizzando il parallelismo tensore su tutti gli otto acceleratori disponibili.

Possiamo notare alcuni suggerimenti da questa figura. Innanzitutto, non tutti i modelli sono supportati su tutte le istanze; alcuni modelli più piccoli, come Falcon 7B, non supportano il partizionamento orizzontale del modello, mentre i modelli più grandi hanno requisiti di risorse di elaborazione più elevati. In secondo luogo, con l'aumento dello sharding, le prestazioni in genere migliorano, ma potrebbero non necessariamente migliorare per i modelli di piccole dimensioniQuesto perché i modelli piccoli come 7B e 13B comportano un notevole sovraccarico di comunicazione quando vengono suddivisi su troppi acceleratori. Ne discuteremo più approfonditamente in seguito. Infine, le istanze ml.p4d.24xlarge tendono ad avere un throughput significativamente migliore grazie ai miglioramenti della larghezza di banda della memoria di A100 rispetto alle GPU A10G. Come vedremo più avanti, la decisione di utilizzare un particolare tipo di istanza dipende dai requisiti di distribuzione, inclusi latenza, velocità effettiva e vincoli di costo.

Come è possibile ottenere questi valori di configurazione di latenza più bassa e throughput più elevato? Iniziamo tracciando il grafico della latenza rispetto al throughput per un endpoint Llama 2 7B su un'istanza ml.g5.12xlarge per un payload con 256 token di input e 256 token di output, come mostrato nella curva seguente. Esiste una curva simile per ogni endpoint LLM distribuito.

Confronta e ottimizza la distribuzione degli endpoint in Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Ricerca verticale. Ai.

All'aumentare della concorrenza, anche il throughput e la latenza aumentano in modo monotono. Pertanto, il punto di latenza più basso si verifica con un valore di richiesta simultanea pari a 1 ed è possibile aumentare in modo conveniente la velocità effettiva del sistema aumentando le richieste simultanee. Esiste un distinto "ginocchio" in questa curva, dove è ovvio che i guadagni di throughput associati alla concorrenza aggiuntiva non superano l'aumento associato della latenza. La posizione esatta di questo ginocchio dipende dal caso d'uso; alcuni professionisti possono definire il knee nel punto in cui viene superato un requisito di latenza pre-specificato (ad esempio, 100 ms/token), mentre altri possono utilizzare benchmark dei test di carico e metodi della teoria delle code come la regola della mezza latenza, e altri ancora possono utilizzare specifiche teoriche dell'acceleratore.

Notiamo inoltre che il numero massimo di richieste simultanee è limitato. Nella figura precedente il tracciamento della linea termina con 192 richieste contemporanee. L'origine di questa limitazione è il limite di timeout di invocazione di SageMaker, in cui gli endpoint SageMaker scadono una risposta di invocazione dopo 60 secondi. Questa impostazione è specifica dell'account e non configurabile per un singolo endpoint. Per gli LLM, la generazione di un numero elevato di token di output può richiedere secondi o addirittura minuti. Pertanto, carichi utili di input o output di grandi dimensioni possono causare il fallimento delle richieste di chiamata. Inoltre, se il numero di richieste simultanee è molto elevato, molte richieste subiranno lunghi tempi di coda, determinando questo limite di timeout di 60 secondi. Ai fini di questo studio, utilizziamo il limite di timeout per definire il throughput massimo possibile per la distribuzione di un modello. È importante sottolineare che, sebbene un endpoint SageMaker possa gestire un gran numero di richieste simultanee senza osservare un timeout della risposta all'invocazione, potresti voler definire il numero massimo di richieste simultanee rispetto al ginocchio nella curva latenza-throughput. Questo è probabilmente il punto in cui inizi a considerare il dimensionamento orizzontale, in cui un singolo endpoint fornisce più istanze con repliche del modello e bilancia il carico delle richieste in entrata tra le repliche, per supportare più richieste simultanee.

Facendo un ulteriore passo avanti, la tabella seguente contiene i risultati del benchmarking per diverse configurazioni per il modello Llama 2 7B, inclusi diversi numeri di token di input e output, tipi di istanze e numero di richieste simultanee. Si noti che la figura precedente traccia solo una singola riga di questa tabella.

. Velocità effettiva (token/sec) Latenza (ms/token)
Richieste simultanee 1 2 4 8 16 32 64 128 256 512 1 2 4 8 16 32 64 128 256 512
Numero di token totali: 512, Numero di token di output: 256
ml.g5.2xgrande 30 54 115 208 343 475 486 - - - 33 33 35 39 48 97 159 - - -
ml.g5.12xgrande 59 117 223 406 616 866 1098 1214 - - 17 17 18 20 27 38 60 112 - -
ml.g5.48xgrande 56 108 202 366 522 660 707 804 - - 18 18 19 22 32 50 101 171 - -
ml.p4d.24xlarge 49 85 178 353 654 1079 1544 2312 2905 2944 21 23 22 23 26 31 44 58 92 165
Numero di token totali: 4096, Numero di token di output: 256
ml.g5.2xgrande 20 36 48 49 - - - - - - 48 57 104 170 - - - - - -
ml.g5.12xgrande 33 58 90 123 142 - - - - - 31 34 48 73 132 - - - - -
ml.g5.48xgrande 31 48 66 82 - - - - - - 31 43 68 120 - - - - - -
ml.p4d.24xlarge 39 73 124 202 278 290 - - - - 26 27 33 43 66 107 - - - -

Osserviamo alcuni modelli aggiuntivi in ​​questi dati. Quando si aumenta la dimensione del contesto, la latenza aumenta e la velocità effettiva diminuisce. Ad esempio, su ml.g5.2xlarge con una concorrenza pari a 1, il throughput è di 30 token/sec quando il numero di token totali è 512, contro 20 token/sec se il numero di token totali è 4,096. Questo perché ci vuole più tempo per elaborare l'input più grande. Possiamo anche vedere che l'aumento della capacità della GPU e dello sharding influiscono sul throughput massimo e sul numero massimo di richieste simultanee supportate. La tabella mostra che Llama 2 7B ha valori di throughput massimo notevolmente diversi per diversi tipi di istanza e questi valori di throughput massimo si verificano a valori diversi di richieste simultanee. Queste caratteristiche spingerebbero un professionista del machine learning a giustificare il costo di un’istanza rispetto a un’altra. Ad esempio, dato un requisito di bassa latenza, il professionista potrebbe selezionare un'istanza ml.g5.12xlarge (4 GPU A10G) rispetto a un'istanza ml.g5.2xlarge (1 GPU A10G). Se viene dato un requisito di throughput elevato, l'uso di un'istanza ml.p4d.24xlarge (8 GPU A100) con sharding completo sarebbe giustificato solo in condizioni di concorrenza elevata. Tieni presente, tuttavia, che spesso è vantaggioso caricare più componenti di inferenza di un modello 7B su una singola istanza ml.p4d.24xlarge; tale supporto multimodello verrà discusso più avanti in questo post.

Le osservazioni precedenti sono state fatte per il modello Llama 2 7B. Tuttavia, modelli simili rimangono validi anche per altri modelli. Il punto principale è che i numeri relativi alle prestazioni di latenza e throughput dipendono dal carico utile, dal tipo di istanza e dal numero di richieste simultanee, quindi dovrai trovare la configurazione ideale per la tua applicazione specifica. Per generare i numeri precedenti per il tuo caso d'uso, puoi eseguire il collegamento taccuino, dove puoi configurare l'analisi del test di carico per il tuo modello, tipo di istanza e payload.

Dare un senso alle specifiche dell'acceleratore

La selezione dell'hardware adatto per l'inferenza LLM dipende in gran parte da casi d'uso specifici, obiettivi dell'esperienza utente e LLM scelto. Questa sezione tenta di creare una comprensione del ginocchio nella curva di latenza-rendimento rispetto ai principi di alto livello basati sulle specifiche dell'acceleratore. Questi principi da soli non sono sufficienti per prendere una decisione: sono necessari parametri di riferimento reali. Il termine dispositivo viene utilizzato qui per comprendere tutti gli acceleratori hardware ML. Affermiamo che il ginocchio nella curva latenza-throughput è guidato da uno dei due fattori:

  • L'acceleratore ha esaurito la memoria per memorizzare nella cache le matrici KV, quindi le richieste successive vengono accodate
  • L'acceleratore dispone ancora di memoria di riserva per la cache KV, ma utilizza una dimensione batch sufficientemente grande da far sì che il tempo di elaborazione sia determinato dalla latenza delle operazioni di calcolo anziché dalla larghezza di banda della memoria

In genere preferiamo essere limitati dal secondo fattore perché ciò implica che le risorse dell’acceleratore sono saturate. Fondamentalmente, stai massimizzando le risorse per cui hai pagato. Esploriamo questa affermazione in maggiore dettaglio.

Caching KV e memoria del dispositivo

I meccanismi standard di attenzione del trasformatore calcolano l'attenzione per ogni nuovo token rispetto a tutti i token precedenti. La maggior parte dei server ML moderni memorizza nella cache le chiavi e i valori di attenzione nella memoria del dispositivo (DRAM) per evitare il ricalcolo a ogni passaggio. Questo si chiama questo il Cache KVe cresce con la dimensione del batch e la lunghezza della sequenza. Definisce quante richieste degli utenti possono essere servite in parallelo e determinerà il ginocchio nella curva latenza-throughput se il regime vincolato al calcolo nel secondo scenario menzionato in precedenza non è ancora soddisfatto, data la DRAM disponibile. La seguente formula è un'approssimazione approssimativa della dimensione massima della cache KV.

Confronta e ottimizza la distribuzione degli endpoint in Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Ricerca verticale. Ai.

In questa formula, B è la dimensione del lotto e N è il numero di acceleratori. Ad esempio, il modello Llama 2 7B in FP16 (2 byte/parametro) servito su una GPU A10G (24 GB DRAM) consuma circa 14 GB, lasciando 10 GB per la cache KV. Inserendo la lunghezza completa del contesto del modello (N = 4096) e i parametri rimanenti (n_layers=32, n_kv_attention_heads=32 e d_attention_head=128), questa espressione mostra che siamo limitati a servire una dimensione batch di quattro utenti in parallelo a causa dei vincoli DRAM . Se osservi i benchmark corrispondenti nella tabella precedente, questa è una buona approssimazione per il ginocchio osservato in questa curva latenza-throughput. Metodi come attenzione alle query raggruppate (GQA) può ridurre la dimensione della cache KV, nel caso di GQA riduce dello stesso fattore il numero di teste KV.

Intensità aritmetica e larghezza di banda della memoria del dispositivo

La crescita della potenza computazionale degli acceleratori ML ha superato la loro larghezza di banda di memoria, il che significa che possono eseguire molti più calcoli su ciascun byte di dati nella quantità di tempo necessaria per accedere a quel byte.

I intensità aritmetica, o il rapporto tra le operazioni di calcolo e gli accessi alla memoria, per un'operazione determina se è limitata dalla larghezza di banda della memoria o dalla capacità di calcolo sull'hardware selezionato. Ad esempio, una GPU A10G (famiglia di tipi di istanza g5) con 70 TFLOPS FP16 e larghezza di banda di 600 GB/sec può calcolare circa 116 operazioni/byte. Una GPU A100 (famiglia di tipi di istanza p4d) può elaborare circa 208 operazioni/byte. Se l'intensità aritmetica per un modello di trasformatore è inferiore a tale valore, è legato alla memoria; se è superiore, è vincolato al calcolo. Il meccanismo di attenzione per Llama 2 7B richiede 62 ops/byte per batch size 1 (per una spiegazione, vedere Una guida all'inferenza e alle prestazioni LLM), il che significa che è legato alla memoria. Quando il meccanismo di attenzione è legato alla memoria, i costosi FLOPS vengono lasciati inutilizzati.

Esistono due modi per utilizzare meglio l'acceleratore e aumentare l'intensità aritmetica: ridurre gli accessi alla memoria richiesti per l'operazione (questo è ciò che FlashAttenzione si concentra) o aumentare la dimensione del batch. Tuttavia, potremmo non essere in grado di aumentare la dimensione del batch abbastanza da raggiungere un regime vincolato al calcolo se la nostra DRAM è troppo piccola per contenere la cache KV corrispondente. Un'approssimazione approssimativa della dimensione critica del batch B* che separa i regimi legati al calcolo da quelli legati alla memoria per l'inferenza del decodificatore GPT standard è descritta dalla seguente espressione, dove A_mb è la larghezza di banda della memoria dell'acceleratore, A_f è i FLOPS dell'acceleratore e N è il numero degli acceleratori. Questa dimensione batch critica può essere derivata trovando dove il tempo di accesso alla memoria equivale al tempo di calcolo. Fare riferimento a questo post del blog per comprendere l'equazione 2 e le sue ipotesi in maggiore dettaglio.

Confronta e ottimizza la distribuzione degli endpoint in Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Ricerca verticale. Ai.

Questo è lo stesso rapporto operazioni/byte calcolato in precedenza per A10G, quindi la dimensione critica del batch su questa GPU è 116. Un modo per avvicinarsi a questa dimensione teorica e critica del batch è aumentare lo sharding del modello e dividere la cache su più N acceleratori. Ciò aumenta effettivamente la capacità della cache KV e la dimensione del batch legato alla memoria.

Un altro vantaggio dello sharding del modello è la suddivisione dei parametri del modello e del lavoro di caricamento dei dati tra N acceleratori. Questo tipo di sharding è un tipo di parallelismo del modello chiamato anche parallelismo tensoriale. Ingenuamente, ci sono N volte la larghezza di banda della memoria e la potenza di calcolo in totale. Supponendo che non vi sia alcun sovraccarico di alcun tipo (comunicazione, software e così via), ciò ridurrebbe la latenza di decodifica per token di N se siamo vincolati alla memoria, poiché la latenza di decodifica dei token in questo regime è vincolata dal tempo necessario per caricare il modello pesi e cache. Nella vita reale, tuttavia, l'aumento del grado di partizionamento orizzontale si traduce in una maggiore comunicazione tra i dispositivi per condividere attivazioni intermedie a ogni livello del modello. Questa velocità di comunicazione è limitata dalla larghezza di banda di interconnessione del dispositivo. È difficile stimare con precisione il suo impatto (per i dettagli, cfr Parallelismo modello), ma questo alla fine può non apportare più vantaggi o peggiorare le prestazioni; questo è particolarmente vero per i modelli più piccoli, perché trasferimenti di dati più piccoli portano a velocità di trasferimento inferiori.

Per confrontare gli acceleratori ML in base alle specifiche, consigliamo quanto segue. Innanzitutto, calcolare la dimensione critica approssimativa del batch per ciascun tipo di acceleratore secondo la seconda equazione e la dimensione della cache KV per la dimensione critica del batch secondo la prima equazione. È quindi possibile utilizzare la DRAM disponibile sull'acceleratore per calcolare il numero minimo di acceleratori richiesti per soddisfare la cache KV e i parametri del modello. Se si decide tra più acceleratori, dare la priorità agli acceleratori in base al costo più basso per GB/sec di larghezza di banda della memoria. Infine, confronta queste configurazioni e verifica qual è il miglior costo/token per il limite superiore della latenza desiderata.

Seleziona una configurazione di distribuzione dell'endpoint

Molti LLM distribuiti da SageMaker JumpStart utilizzano il file inferenza di generazione del testo (TGI) Contenitore SageMaker per servire il modello. La tabella seguente illustra come regolare una serie di parametri di fornitura del modello per influenzare la fornitura del modello che influisce sulla curva di latenza-velocità effettiva o proteggere l'endpoint dalle richieste che sovraccaricherebbero l'endpoint. Questi sono i parametri principali che puoi utilizzare per configurare la distribuzione dell'endpoint per il tuo caso d'uso. Se non diversamente specificato, utilizziamo default parametri del payload di generazione del testo ed Variabili d'ambiente TGI.

Variabile d'ambiente Descrizione Valore predefinito di SageMaker JumpStart
Configurazioni di servizio del modello . .
MAX_BATCH_PREFILL_TOKENS Limita il numero di token nell'operazione di precompilazione. Questa operazione genera la cache KV per una nuova sequenza di prompt di input. Richiede un utilizzo intensivo della memoria e dei calcoli, quindi questo valore limita il numero di token consentiti in una singola operazione di precompilazione. I passaggi di decodifica per altre query vengono sospesi durante la precompilazione. 4096 (impostazione predefinita TGI) o la lunghezza massima del contesto supportata specifica del modello (fornito da SageMaker JumpStart), a seconda di quale sia maggiore.
MAX_BATCH_TOTAL_TOKENS Controlla il numero massimo di token da includere in un batch durante la decodifica o un singolo passaggio in avanti attraverso il modello. Idealmente, questo è impostato per massimizzare l'utilizzo di tutto l'hardware disponibile. Non specificato (impostazione predefinita TGI). TGI imposterà questo valore rispetto alla memoria CUDA rimanente durante il riscaldamento del modello.
SM_NUM_GPUS Il numero di frammenti da utilizzare. Cioè, il numero di GPU utilizzate per eseguire il modello utilizzando il parallelismo del tensore. Dipendente dall'istanza (fornito con SageMaker JumpStart). Per ogni istanza supportata per un determinato modello, SageMaker JumpStart fornisce l'impostazione migliore per il parallelismo del tensore.
Configurazioni per proteggere il tuo endpoint (impostale per il tuo caso d'uso) . .
MAX_TOTAL_TOKENS Ciò limita il budget di memoria di una singola richiesta del client limitando il numero di token nella sequenza di input più il numero di token nella sequenza di output (il max_new_tokens parametro di carico utile). Lunghezza massima del contesto supportata specifica del modello. Ad esempio, 4096 per Lama 2.
MAX_INPUT_LENGTH Identifica il numero massimo consentito di token nella sequenza di input per una singola richiesta client. Gli aspetti da considerare quando si aumenta questo valore includono: sequenze di input più lunghe richiedono più memoria, il che influisce sul batch continuo e molti modelli hanno una lunghezza del contesto supportata che non deve essere superata. Lunghezza massima del contesto supportata specifica del modello. Ad esempio, 4095 per Lama 2.
MAX_CONCURRENT_REQUESTS Il numero massimo di richieste simultanee consentite dall'endpoint distribuito. Le nuove richieste oltre questo limite genereranno immediatamente un errore di sovraccarico del modello per evitare una scarsa latenza per le richieste di elaborazione correnti. 128 (predefinito TGI). Questa impostazione ti consente di ottenere un throughput elevato per una varietà di casi d'uso, ma dovresti bloccarla in modo appropriato per mitigare gli errori di timeout di chiamata di SageMaker.

Il server TGI utilizza il batch continuo, che raggruppa dinamicamente insieme richieste simultanee per condividere un singolo passaggio in avanti di inferenza del modello. Esistono due tipi di passaggi in avanti: precompilazione e decodifica. Ogni nuova richiesta deve eseguire un singolo passaggio di precompilazione per popolare la cache KV per i token della sequenza di input. Dopo che la cache KV è stata popolata, un passaggio di decodifica in avanti esegue una singola previsione del token successivo per tutte le richieste in batch, che viene ripetuta in modo iterativo per produrre la sequenza di output. Quando nuove richieste vengono inviate al server, il passaggio di decodifica successivo deve attendere affinché il passaggio di precompilazione possa essere eseguito per le nuove richieste. Ciò deve avvenire prima che le nuove richieste vengano incluse nei successivi passaggi di decodifica batch continui. A causa di vincoli hardware, il batch continuo utilizzato per la decodifica potrebbe non includere tutte le richieste. A questo punto, le richieste entrano in una coda di elaborazione e la latenza di inferenza inizia ad aumentare in modo significativo con un guadagno di throughput solo minimo.

È possibile separare le analisi di benchmarking della latenza LLM in latenza di precompilazione, latenza di decodifica e latenza di coda. Il tempo impiegato da ciascuno di questi componenti è di natura fondamentalmente diversa: la precompilazione è un calcolo eseguito una sola volta, la decodifica avviene una volta per ciascun token nella sequenza di output e l'accodamento implica processi di batching del server. Quando vengono elaborate più richieste simultanee, diventa difficile distinguere le latenze da ciascuno di questi componenti poiché la latenza sperimentata da una determinata richiesta del client coinvolge latenze di coda guidate dalla necessità di precompilare nuove richieste simultanee nonché latenze di coda guidate dall'inclusione della richiesta nei processi di decodifica batch. Per questo motivo, questo post si concentra sulla latenza di elaborazione end-to-end. Il ginocchio nella curva latenza-throughput si verifica nel punto di saturazione in cui le latenze delle code iniziano ad aumentare in modo significativo. Questo fenomeno si verifica per qualsiasi server di inferenza del modello ed è guidato dalle specifiche dell'acceleratore.

I requisiti comuni durante la distribuzione includono il soddisfacimento del throughput minimo richiesto, la latenza massima consentita, il costo orario massimo e il costo massimo per generare 1 milione di token. Dovresti condizionare questi requisiti sui payload che rappresentano le richieste degli utenti finali. Una progettazione per soddisfare questi requisiti dovrebbe considerare molti fattori, tra cui l'architettura specifica del modello, le dimensioni del modello, i tipi di istanza e il numero di istanze (ridimensionamento orizzontale). Nelle sezioni seguenti ci concentreremo sulla distribuzione degli endpoint per ridurre al minimo la latenza, massimizzare il throughput e ridurre al minimo i costi. Questa analisi considera 512 token totali e 256 token di output.

Minimizza la latenza

La latenza è un requisito importante in molti casi d'uso in tempo reale. Nella tabella seguente esaminiamo la latenza minima per ciascun modello e ciascun tipo di istanza. È possibile ottenere una latenza minima impostando MAX_CONCURRENT_REQUESTS = 1.

Latenza minima (ms/token)
ID modello ml.g5.2xgrande ml.g5.12xgrande ml.g5.48xgrande ml.p4d.24xlarge ml.p4de.24xlarge
Lama 2 7B 33 17 18 20 -
Lama 2 7B Chat 33 17 18 20 -
Lama 2 13B - 22 23 23 -
Lama 2 13B Chat - 23 23 23 -
Lama 2 70B - - 57 43 -
Lama 2 70B Chat - - 57 45 -
Maestrale 7B 35 - - - -
Mistral 7B Istruzione 35 - - - -
Mixtral 8x7B - - 33 27 -
Falcon 7B 33 - - - -
Falcon 7B Istruttore 33 - - - -
Falcon 40B - 53 33 27 -
Falcon 40B Istruttore - 53 33 28 -
Falcon 180B - - - - 42
Chatta sul Falcon 180B - - - - 42

Per ottenere una latenza minima per un modello, puoi utilizzare il seguente codice sostituendo l'ID modello e il tipo di istanza desiderati:

from sagemaker.jumpstart.model import JumpStartModel model = JumpStartModel( model_id="meta-textgeneration-llama-2-7b", model_version="3.*", instance_type="ml.g5.12xlarge", env={ "MAX_CONCURRENT_REQUESTS": "1", "MAX_INPUT_TOKENS": "256", "MAX_TOTAL_TOKENS": "512", },
)
predictor = model.deploy(accept_eula=False) # Change EULA acceptance to True

Tieni presente che i numeri di latenza cambiano a seconda del numero di token di input e output. Tuttavia, il processo di distribuzione rimane lo stesso, ad eccezione delle variabili di ambiente MAX_INPUT_TOKENS ed MAX_TOTAL_TOKENS. In questo caso, queste variabili di ambiente sono impostate per garantire i requisiti di latenza dell'endpoint poiché sequenze di input più grandi potrebbero violare il requisito di latenza. Tieni presente che SageMaker JumpStart fornisce già le altre variabili di ambiente ottimali quando si seleziona il tipo di istanza; ad esempio, utilizzando ml.g5.12xlarge verrà impostato SM_NUM_GPUS a 4 nell'ambiente modello.

Massimizza la produttività

In questa sezione massimizziamo il numero di token generati al secondo. Ciò si ottiene in genere al numero massimo di richieste simultanee valide per il modello e il tipo di istanza. Nella tabella seguente riportiamo il throughput raggiunto al valore massimo di richieste simultanee raggiunto prima di incontrare un timeout di invocazione SageMaker per qualsiasi richiesta.

Throughput massimo (token/sec), richieste simultanee
ID modello ml.g5.2xgrande ml.g5.12xgrande ml.g5.48xgrande ml.p4d.24xlarge ml.p4de.24xlarge
Lama 2 7B 486 (64) 1214 (128) 804 (128) 2945 (512) -
Lama 2 7B Chat 493 (64) 1207 (128) 932 (128) 3012 (512) -
Lama 2 13B - 787 (128) 496 (64) 3245 (512) -
Lama 2 13B Chat - 782 (128) 505 (64) 3310 (512) -
Lama 2 70B - - 124 (16) 1585 (256) -
Lama 2 70B Chat - - 114 (16) 1546 (256) -
Maestrale 7B 947 (64) - - - -
Mistral 7B Istruzione 986 (128) - - - -
Mixtral 8x7B - - 701 (128) 3196 (512) -
Falcon 7B 1340 (128) - - - -
Falcon 7B Istruttore 1313 (128) - - - -
Falcon 40B - 244 (32) 382 (64) 2699 (512) -
Falcon 40B Istruttore - 245 (32) 415 (64) 2675 (512) -
Falcon 180B - - - - 1100 (128)
Chatta sul Falcon 180B - - - - 1081 (128)

Per ottenere il massimo throughput per un modello, è possibile utilizzare il seguente codice:

from sagemaker.jumpstart.model import JumpStartModel model = JumpStartModel( model_id="meta-textgeneration-llama-2-7b", model_version="3.*", instance_type="ml.g5.12xlarge", env={ "MAX_CONCURRENT_REQUESTS": "128", # For your application, identify it from the benchmarking table with the maximum feasible concurrent requests. "MAX_INPUT_TOKENS": "256", "MAX_TOTAL_TOKENS": "512", },
)
predictor = model.deploy(accept_eula=False) # Change EULA acceptance to True

Tieni presente che il numero massimo di richieste simultanee dipende dal tipo di modello, dal tipo di istanza, dal numero massimo di token di input e dal numero massimo di token di output. Pertanto, è necessario impostare questi parametri prima dell'impostazione MAX_CONCURRENT_REQUESTS.

Tieni inoltre presente che un utente interessato a ridurre al minimo la latenza è spesso in contrasto con un utente interessato a massimizzare il throughput. Il primo è interessato alle risposte in tempo reale, mentre il secondo è interessato all'elaborazione batch in modo tale che la coda dell'endpoint sia sempre saturata, riducendo così al minimo i tempi di inattività dell'elaborazione. Gli utenti che desiderano massimizzare il throughput in base ai requisiti di latenza sono spesso interessati a operare in corrispondenza della curva latenza-throughput.

Ridurre al minimo i costi

La prima opzione per ridurre al minimo i costi consiste nel ridurre al minimo il costo orario. Con questo, puoi distribuire un modello selezionato sull'istanza SageMaker con il costo orario più basso. Per i prezzi in tempo reale delle istanze SageMaker, fare riferimento a Prezzi di Amazon SageMaker. In generale, il tipo di istanza predefinito per i LLM SageMaker JumpStart rappresenta l'opzione di distribuzione dal costo più basso.

La seconda opzione per ridurre al minimo i costi implica ridurre al minimo il costo per generare 1 milione di token. Questa è una semplice trasformazione della tabella di cui abbiamo discusso in precedenza per massimizzare il throughput, in cui puoi prima calcolare il tempo impiegato in ore per generare 1 milione di token (1e6 / throughput / 3600). Puoi quindi moltiplicare questo tempo per generare 1 milione di token con il prezzo orario dell'istanza SageMaker specificata.

Tieni presente che le istanze con il costo orario più basso non corrispondono alle istanze con il costo più basso per generare 1 milione di token. Ad esempio, se le richieste di chiamata sono sporadiche, un'istanza con il costo orario più basso potrebbe essere ottimale, mentre negli scenari di limitazione, il costo più basso per generare un milione di token potrebbe essere più appropriato.

Compromesso tra parallelo tensore e multimodello

In tutte le analisi precedenti, abbiamo considerato la distribuzione di una singola replica del modello con un grado di parallelo tensore pari al numero di GPU sul tipo di istanza di distribuzione. Questo è il comportamento JumpStart predefinito di SageMaker. Tuttavia, come notato in precedenza, lo sharding di un modello può migliorare la latenza e il throughput del modello solo fino a un certo limite, oltre il quale i requisiti di comunicazione tra dispositivi dominano il tempo di calcolo. Ciò implica che spesso è vantaggioso distribuire più modelli con un grado di parallelo tensoriale inferiore su una singola istanza anziché un singolo modello con un grado di parallelo tensoriale più elevato.

Qui distribuiamo gli endpoint Llama 2 7B e 13B su istanze ml.p4d.24xlarge con gradi tensore parallelo (TP) di 1, 2, 4 e 8. Per chiarezza nel comportamento del modello, ciascuno di questi endpoint carica solo un singolo modello.

. Velocità effettiva (token/sec) Latenza (ms/token)
Richieste simultanee 1 2 4 8 16 32 64 128 256 512 1 2 4 8 16 32 64 128 256 512
Laurea TP Lama 2 13B
1 38 74 147 278 443 612 683 722 - - 26 27 27 29 37 45 87 174 - -
2 49 92 183 351 604 985 1435 1686 1726 - 21 22 22 22 25 32 46 91 159 -
4 46 94 181 343 655 1073 1796 2408 2764 2819 23 21 21 24 25 30 37 57 111 172
8 44 86 158 311 552 1015 1654 2450 3087 3180 22 24 26 26 29 36 42 57 95 152
. Lama 2 7B
1 62 121 237 439 778 1122 1569 1773 1775 - 16 16 17 18 22 28 43 88 151 -
2 62 122 239 458 780 1328 1773 2440 2730 2811 16 16 17 18 21 25 38 56 103 182
4 60 106 211 420 781 1230 2206 3040 3489 3752 17 19 20 18 22 27 31 45 82 132
8 49 97 179 333 612 1081 1652 2292 2963 3004 22 20 24 26 27 33 41 65 108 167

Le nostre analisi precedenti hanno già mostrato vantaggi significativi in ​​termini di throughput sulle istanze ml.p4d.24xlarge, che spesso si traducono in migliori prestazioni in termini di costi per generare 1 milione di token rispetto alla famiglia di istanze g5 in condizioni di carico di richieste simultanee elevate. Questa analisi dimostra chiaramente che è necessario considerare il compromesso tra partizionamento orizzontale e replica del modello all'interno di una singola istanza; ovvero, un modello completamente partizionato non è in genere il miglior utilizzo delle risorse di calcolo ml.p4d.24xlarge per le famiglie di modelli 7B e 13B. Infatti, per la famiglia di modelli 7B, si ottiene il miglior throughput per una singola replica del modello con un grado di parallelo tensore di 4 anziché 8.

Da qui, puoi estrapolare che la configurazione di throughput più elevato per il modello 7B prevede un grado di parallelo tensore di 1 con otto repliche del modello e che la configurazione di throughput più elevato per il modello 13B è probabilmente un grado di parallelo tensore di 2 con quattro repliche del modello. Per ulteriori informazioni su come eseguire questa operazione, fare riferimento a Riduci i costi di distribuzione del modello in media del 50% utilizzando le funzionalità più recenti di Amazon SageMaker, che dimostra l'uso di endpoint basati su componenti di inferenza. A causa delle tecniche di bilanciamento del carico, del routing del server e della condivisione delle risorse della CPU, potresti non ottenere miglioramenti completi della velocità effettiva esattamente pari al numero di repliche moltiplicato per la velocità effettiva di una singola replica.

Ridimensionamento orizzontale

Come osservato in precedenza, ogni distribuzione di endpoint presenta una limitazione sul numero di richieste simultanee a seconda del numero di token di input e output, nonché del tipo di istanza. Se ciò non soddisfa i tuoi requisiti di velocità effettiva o di richieste simultanee, puoi aumentare le prestazioni per utilizzare più di un'istanza dietro l'endpoint distribuito. SageMaker esegue automaticamente il bilanciamento del carico delle query tra le istanze. Ad esempio, il codice seguente distribuisce un endpoint supportato da tre istanze:

model = JumpStartModel( model_id="meta-textgeneration-llama-2-7b", model_version="3.*", instance_type="ml.g5.2xlarge",
)
predictor = model.deploy( accept_eula=False, # Change EULA acceptance to True initial_instance_count = 3,
)

La tabella seguente mostra il guadagno di throughput come fattore del numero di istanze per il modello Llama 2 7B.

. . Velocità effettiva (token/sec) Latenza (ms/token)
. Richieste simultanee 1 2 4 8 16 32 64 128 1 2 4 8 16 32 64 128
Conteggio istanze Tipo di istanza Numero di token totali: 512, Numero di token di output: 256
1 ml.g5.2xgrande 30 60 115 210 351 484 492 - 32 33 34 37 45 93 160 -
2 ml.g5.2xgrande 30 60 115 221 400 642 922 949 32 33 34 37 42 53 94 167
3 ml.g5.2xgrande 30 60 118 228 421 731 1170 1400 32 33 34 36 39 47 57 110

In particolare, il ginocchio nella curva latenza-throughput si sposta verso destra perché un numero maggiore di istanze può gestire un numero maggiore di richieste simultanee all'interno dell'endpoint multiistanza. Per questa tabella, il valore della richiesta simultanea si riferisce all'intero endpoint, non al numero di richieste simultanee ricevute da ogni singola istanza.

Puoi anche utilizzare la scalabilità automatica, una funzionalità per monitorare i carichi di lavoro e regolare dinamicamente la capacità per mantenere prestazioni costanti e prevedibili al costo più basso possibile. Questo va oltre lo scopo di questo post. Per ulteriori informazioni sulla scalabilità automatica, fare riferimento a Configurazione degli endpoint di inferenza con scalabilità automatica in Amazon SageMaker.

Richiamare l'endpoint con richieste simultanee

Supponiamo che tu abbia un grande batch di query che vorresti utilizzare per generare risposte da un modello distribuito in condizioni di throughput elevato. Ad esempio, nel blocco di codice seguente compiliamo un elenco di 1,000 payload, ciascuno dei quali richiede la generazione di 100 token. In tutto chiediamo la generazione di 100,000 token.

payload = { "inputs": "I believe the meaning of life is to ", "parameters": {"max_new_tokens": 100, "details": True},
}
total_requests = 1000
payloads = [payload,] * total_requests

Quando si invia un numero elevato di richieste all'API runtime SageMaker, potrebbero verificarsi errori di limitazione. Per mitigare questo problema, puoi creare un client runtime SageMaker personalizzato che aumenta il numero di tentativi. È possibile fornire l'oggetto sessione SageMaker risultante al file JumpStartModel costruttore o sagemaker.predictor.retrieve_default se desideri collegare un nuovo predittore a un endpoint già distribuito. Nel codice seguente, utilizziamo questo oggetto sessione durante la distribuzione di un modello Llama 2 con configurazioni JumpStart SageMaker predefinite:

import boto3
from botocore.config import Config
from sagemaker.session import Session
from sagemaker.jumpstart.model import JumpStartModel sagemaker_session = Session( sagemaker_runtime_client=boto3.client( "sagemaker-runtime", config=Config(connect_timeout=10, retries={"mode": "standard", "total_max_attempts": 20}), )
)
model = JumpStartModel( model_id="meta-textgeneration-llama-2-7b", model_version="3.*", sagemaker_session=sagemaker_session
)
predictor = model.deploy(accept_eula=False) # Change EULA acceptance to True

Questo endpoint distribuito ha MAX_CONCURRENT_REQUESTS = 128 per impostazione predefinita. Nel blocco seguente, utilizziamo la libreria dei futures simultanei per ripetere l'invocazione dell'endpoint per tutti i payload con 128 thread di lavoro. Al massimo, l'endpoint elaborerà 128 richieste simultanee e ogni volta che una richiesta restituisce una risposta, l'esecutore invierà immediatamente una nuova richiesta all'endpoint.

import time
from concurrent import futures concurrent_requests = 128 time_start = time.time()
with futures.ThreadPoolExecutor(max_workers=concurrent_requests) as executor: responses = list(executor.map(predictor.predict, payloads)) total_tokens = sum([response[0]["details"]["generated_tokens"] for response in responses])
token_throughput = total_tokens / (time.time() - time_start)

Ciò si traduce nella generazione di 100,000 token totali con un throughput di 1255 token/sec su una singola istanza ml.g5.2xlarge. L'elaborazione richiede circa 80 secondi.

Tieni presente che questo valore di throughput è notevolmente diverso dal throughput massimo per Llama 2 7B su ml.g5.2xlarge nelle tabelle precedenti di questo post (486 token/sec a 64 richieste simultanee). Questo perché il payload di input utilizza 8 token invece di 256, il conteggio dei token di output è 100 invece di 256 e i conteggi di token più piccoli consentono 128 richieste simultanee. Questo è un ultimo promemoria del fatto che tutti i numeri di latenza e throughput dipendono dal carico utile! La modifica del conteggio dei token del payload influirà sui processi di batching durante l'offerta del modello, che a sua volta influirà sui tempi di precompilazione, decodifica e coda emergenti per l'applicazione.

Conclusione

In questo post abbiamo presentato il benchmarking degli LLM SageMaker JumpStart, tra cui Llama 2, Mistral e Falcon. Abbiamo inoltre presentato una guida per ottimizzare la latenza, la velocità effettiva e i costi per la configurazione di distribuzione dell'endpoint. Puoi iniziare eseguendo il file taccuino associato per valutare il tuo caso d'uso.


Informazioni sugli autori

Confronta e ottimizza la distribuzione degli endpoint in Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Ricerca verticale. Ai.  Dottor Kyle Ulrich è uno scienziato applicato del team JumpStart di Amazon SageMaker. I suoi interessi di ricerca includono algoritmi scalabili di apprendimento automatico, visione artificiale, serie temporali, parametri bayesiani non parametrici e processi gaussiani. Ha conseguito il dottorato di ricerca presso la Duke University e ha pubblicato articoli su NeurIPS, Cell e Neuron.

Confronta e ottimizza la distribuzione degli endpoint in Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Ricerca verticale. Ai.Dr. Vivek Madan è uno scienziato applicato con il team Amazon SageMaker JumpStart. Ha conseguito il dottorato di ricerca presso l'Università dell'Illinois a Urbana-Champaign ed è stato ricercatore post-dottorato presso la Georgia Tech. È un ricercatore attivo nell'apprendimento automatico e nella progettazione di algoritmi e ha pubblicato articoli in conferenze EMNLP, ICLR, COLT, FOCS e SODA.

Confronta e ottimizza la distribuzione degli endpoint in Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Ricerca verticale. Ai.Dottor Ashish Khetan è uno scienziato applicato senior presso Amazon SageMaker JumpStart e aiuta a sviluppare algoritmi di apprendimento automatico. Ha conseguito il dottorato di ricerca presso l'Università dell'Illinois Urbana-Champaign. È un ricercatore attivo nel campo dell'apprendimento automatico e dell'inferenza statistica e ha pubblicato numerosi articoli nelle conferenze NeurIPS, ICML, ICLR, JMLR, ACL e EMNLP.

Confronta e ottimizza la distribuzione degli endpoint in Amazon SageMaker JumpStart | Amazon Web Services PlatoBlockchain Data Intelligence. Ricerca verticale. Ai.João Moura è un Senior AI/ML Specialist Solutions Architect presso AWS. João aiuta i clienti AWS, dalle piccole startup alle grandi imprese, ad addestrare e distribuire modelli di grandi dimensioni in modo efficiente e, più in generale, a costruire piattaforme ML su AWS.

Timestamp:

Di più da Apprendimento automatico di AWS