Configurazione di vLLM per massima prestazione

Fonte

I parametri dell’engine vLLM che discuteremo:

  • max-num-batched-tokens
  • max-model-len
  • gpu-memory-utilization
  • enable-prefix-caching
  • enable-chunked-prefill
  • enforce-eager

max-model-len:

TL;DR in base al numero massimo di token utilizzati (input + output)

  • Per impostazione predefinita, la lunghezza massima del modello è uguale alla lunghezza massima del contesto della vostra modello. Ad esempio, per il modello llama 3 8B instruct sarà pari a 8192.
  • Se è possibile determinare la lunghezza massima del contesto per il vostro caso d’uso e se è inferiore alla lunghezza massima del contesto del vostro modello, è meglio impostare questo parametro su tale valore.
  • Questo non solo eviterà errori di mancanza di memoria durante il caricamento o l’uso del modello, ma aiuterà anche a configurare altri parametri, come max-num-batched-tokens e gpu-memory-utilization.
  • Il valore include sia il numero di token di input che di output, quindi, se nel vostro caso il numero totale di token non supera, diciamo, 2046, impostate questo parametro su tale valore.

max-num-batched-tokens:

TL;DR iniziare da max-model-len, poi provare a raddoppiarlo: max-model-len*2, poi *3… fino a quando non si ottiene un errore di mancanza di memoria o un avviso di spostamento. Scegliere un valore che garantisca una buona performance. Se si utilizza enable-chunked-prefill, iniziare con un valore più basso, ad esempio 128, e provare diversi valori. Vedi le spiegazioni di seguito.

  • Nota che questo parametro indica il numero di token, non la dimensione del batch.
  • Ogni richiesta deve attraversare la fase di prefill (calcolo dei valori KV per i token di input e distribuzione nei blocchi di cache KV), e poi la fase di decoding, in cui si effettua il calcolo ricorsivo per ottenere i token uno per uno.
  • Di conseguenza, il valore minimo di questo parametro è pari alla lunghezza massima del modello che si è impostato per il prefill (a meno che non si utilizzi chunked-prefill, di cui si parlerà più avanti).
  • Maggiore è il numero di token nel batch, maggiore sarà il numero di prefill, il che significa che il primo token sarà generato più velocemente. Il pianificatore vLLM predefinito preferisce i prefill.
  • Di conseguenza, un grande batch può aiutare ad aumentare la capacità di throughput, ma non funziona in tutti i casi, poiché la capacità e la latenza dipendono anche dal rapporto tra risorse computazionali e memoria GPU (più dettagli nel paragrafo chunked-prefill), e, in generale, i prefill richiedono risorse computazionali maggiori, quindi raggiungono rapidamente il massimo numero di token nel batch che possiamo conservare.
  • Quindi, meglio iniziare con il valore max-model-len, provare a raddoppiarlo e vedere come cambia la performance, fino a quando non si verifica un errore di mancanza di memoria o un avviso di spostamento, come indicato qui, per scegliere il numero corretto di token nel batch. Poi provare ad applicare questa teoria per capire come funziona il vostro sistema.

enable-prefix-caching:

In breve attivarlo se non si utilizza enable-chunked-prefill

  • Memorizza i valori KV calcolati per un uso successivo, permettendo di risparmiare molto tempo.
  • Se gran parte della vostra richiesta rimane invariata all’input, noterete un miglioramento significativo della performance rispetto a una configurazione in cui una piccola parte dei token della richiesta rimane invariata.
  • Se si utilizza il parametro enable-chunked-prefill, questo parametro non è consentito (al momento della pubblicazione di questo post).

gpu-memory-utilization:

TL;DR più alto è meglio, a meno che non si verifichi un errore di mancanza di memoria. Predefinito 0,9

  • Maggiore è la memoria GPU assegnata per memorizzare la cache KV, migliore è la performance.
  • Riducete questo valore se siete stati colpiti da un errore di mancanza di memoria o se la GPU sta eseguendo un’altra attività che richiede una riduzione di questo valore.

enforce-eager:

TL;DR se manca memoria, attivate questa funzione

  • Quando è attivata, non viene creato un grafo CUDA, il che può influenzare la performance, ma permette di risparmiare memoria che sarebbe stata necessaria per il grafo.
  • In alcune configurazioni, il grafo CUDA non influenzerà significativamente la performance, e la memoria risparmiata può essere utile per aumentare i valori dei parametri sopra citati, come gpu-memory-utilization, max-num-batched-tokens, ecc.

enable-chunked-prefill:

TL;DR provate ad attivare questa funzione e utilizzate i token batch, partendo da un valore di 128 e aumentandolo gradualmente. Confrontate con la configurazione senza questo parametro. Vedi le spiegazioni di seguito.

  • La fase di decoding richiede meno risorse computazionali rispetto al prefill (moltiplicazione di un vettore per una matrice invece di moltiplicazione di matrici), ma richiede più memoria, poiché deve leggere i valori KV calcolati.
  • Se volete saperne di più, consultate questo articolo e questa pagina vLLM.
  • Come già detto, il pianificatore vLLM predefinito preferisce il prefill, che richiede risorse computazionali, mentre durante il decoding la memoria diventa il punto di bottiglia, impedendo di sfruttare appieno il decoding con basso consumo di risorse computazionali ma alta richiesta di memoria, poiché è necessario leggere i valori KV.
  • Chunk prefill suddivide la fase di prefill in frammenti, permettendo di ridurre il numero di token nel batch e di formare il batch inizialmente raccolgendo le richieste di decoding e aggiungendo richieste di suddivisione in frammenti per il prefill, per sfruttare in modo efficiente le risorse della GPU, combinando sia il frammentazione computazionalmente intensiva del prefill che un numero sufficiente di richieste di decoding a basso consumo computazionale ma alta richiesta di memoria.
  • Provate nuovamente ad attivare questa funzione e utilizzare un numero ridotto di token nel batch, ad esempio 128, e aumentatelo gradualmente fino a ottenere le prestazioni desiderate in termini di capacità e latenza.
  • Questo metodo può aiutare a ridurre la latenza tra i token, poiché il decoding ha priorità a causa del piccolo batch (che riduce la pressione sulla memoria), ma può influenzare la capacità, quindi è necessario provare diversi batch e confrontare i risultati quando questo parametro non è attivo.

Esempio:

  • Utilizzeremo l’API di ingresso vLLM entrypoints invece del server compatibile con OpenAI
  • Per avviare il server senza prefill chunked, si può usare l’esempio seguente:
python3 -m vllm.entrypoints.api_server — model MaziyarPanahi/Meta-Llama-3–8B-Instruct-GPTQ — gpu-memory-utilization 0.95 — port 5000 — dtype half — enforce-eager — max-model-len 4096 — max-num-batched-tokens 8192 — enable-prefix-caching
  • Se è attivato il prefill chunked, il comando potrebbe essere:
python3 -m vllm.entrypoints.api_server — model MaziyarPanahi/Meta-Llama-3–8B-Instruct-GPTQ — gpu-memory-utilization 0.95 — port 5000 — dtype half — enforce-eager — max-model-len 4096 — max-num-batched-tokens 256 — enable-chunked-prefill
  • Inviate una richiesta alla fine del server indicata sopra per verificare la performance con diversi parametri.
  • Eseguite un benchmark utilizzando i script forniti da vLLM, e io cercherò di scrivere uno script simile e condividerlo qui.

Dall’autore