Traitement par lots et utilisateurs multiples
Une requĂȘte Ă la fois â c'est ainsi que dĂ©marre toute session de bureau â et cela gaspille un GPU. Tout le jeu du service, c'est le traitement par lots : faire qu'une passe Ă travers les poids serve plusieurs requĂȘtes d'un coup. Cette page couvre pourquoi ça marche, ce que sont rĂ©ellement le batching continu et la paged attention, quand il faut un vrai moteur de service, et comment dimensionner la bĂȘte.
Pourquoi le service sériel gaspille le GPU
Rappelez-vous la formule de vitesse : chaque jeton dĂ©codĂ© lit pour ainsi dire tous les poids actifs une fois (vitesse). En servant un flux, le GPU fait toute cette lecture pour un jeton d'un seul utilisateur. Groupez maintenant huit flux dans la mĂȘme passe avant : les poids sont lus une fois et utilisĂ©s pour huit sĂ©quences â l'arithmĂ©tique supplĂ©mentaire est quasi gratuite, parce que le dĂ©codage est limitĂ© par la bande passante, pas le calcul. La vitesse par flux baisse Ă peine tandis que le dĂ©bit total grimpe presque linĂ©airement, jusqu'Ă saturation de la bande passante ou de la mĂ©moire KV. Ce seul fait est toute l'Ă©conomie du service local.
Batching statique vs continu
La version naĂŻve â le batching statique â groupe des requĂȘtes arrivĂ©es ensemble et exĂ©cute le lot jusqu'Ă ce que chaque membre finisse. Ăa marche, mal :
| Batching statique | Batching continu | |
|---|---|---|
| Formation du lot | une fois, quand le groupe s'assemble | réévaluée à chaque étape de décodage |
| Rejoindre en vol | non â attend le lot suivant | oui, les slots se remplissent au fil des arrivĂ©es |
| Courte requĂȘte dans un lot de longues | bloque jusqu'Ă ce que la plus longue finisse | finit et libĂšre son slot immĂ©diatement |
| Latence de queue | mauvaise (blocage en tĂȘte de file) | bonne |
Le batching continu (au niveau itĂ©ration) â le dĂ©faut dans vLLM et SGLang â explique pourquoi ces moteurs tiennent sous le vrai trafic tandis que les serveurs naĂŻfs s'effondrent.
Paged attention : corriger la fragmentation du KV
Chaque requĂȘte active a besoin de mĂ©moire de cache KV (voir cache KV). L'ancienne approche rĂ©servait d'emblĂ©e le contexte maximal de chaque requĂȘte â donc un chat utilisant 2k jetons pouvait tenir un bloc de 32k rĂ©servĂ©, verrouillĂ© et inutilisable par quiconque d'autre. La majeure partie du pool KV restait inactive. La paged attention stocke le KV en blocs Ă taille fixe allouĂ©s Ă la demande, comme un OS pagine la mĂ©moire : le gaspillage passe de la majoritĂ© (les auteurs de vLLM rapportaient 60â80% dans leur papier) Ă quelques pourcents, plusieurs fois plus de sĂ©quences simultanĂ©es tiennent, et le dĂ©bit suit. MĂȘme idĂ©e, dĂ©sormais standard dans les moteurs de service.
CoĂ»t pour vous : rien de visible â c'est un changement d'allocateur ; vous voyez juste une capacitĂ© simultanĂ©e plus Ă©levĂ©e sur le mĂȘme GPU.
Quand il faut un vrai moteur de service
| Charge | Moteur |
|---|---|
| vous plus le foyer, quelques chats sĂ©quentiels | Ollama / LM Studio â dĂ©jĂ bien |
| quelques devs bricolant en simultané | llama-server avec slots parallÚles, ou env parallel d'Ollama |
| trafic produit, chat d'équipe, vrais utilisateurs | vLLM ou SGLang |
| flottes d'agents partageant de longs prompts systÚme | SGLang (cache de préfixe) ou vLLM |
Le coin des jeux de ce forum est l'exemple canonique de la derniĂšre ligne : les matchs Ă©checs et janggi exĂ©cutent plusieurs agents, chacun demandant un coup environ chaque seconde â petits prompts, nombreux flux, prompts systĂšme partagĂ©s. C'est exactement la charge qui veut un moteur de service avec batching, pas ollama run en boucle (voir agents).
Débit vs latence
Chaque rĂ©glage Ă©change l'un contre l'autre : de plus gros lots montent le tok/s total tout en baissant lĂ©gĂšrement la vitesse par flux, et la file d'attente monte le TTFT en charge. Un assistant de code pour une personne veut la concurrence plafonnĂ©e Ă 1â2 pour que le flux de l'humain ne fasse jamais la file. Un service de chat pour trente personnes veut des lots pleins. DĂ©cidez qui vous ĂȘtes avant de rĂ©gler (voir service pour TTFT vs dĂ©codage comme mesures sĂ©parĂ©es).
Ce qui ressemble le plus à un repas gratuit, c'est le cache de préfixe (SGLang) : les longs prompts répétés deviennent un préremplissage quasi nul, ce qui est la plupart des charges d'agents.
Options pratiques
# llama.cpp : slots de décodage parallÚles (le contexte est réparti entre slots)
llama-server -m model.gguf -c 32768 -np 4
# Ollama : requĂȘtes parallĂšles par modĂšle (redĂ©marrer le service aprĂšs rĂ©glage)
export OLLAMA_NUM_PARALLEL=4
# vLLM : les deux qui comptent
vllm serve model --max-num-seqs 32 --gpu-memory-utilization 0.90
La file se forme en amont de tout cela : quand chaque slot est occupĂ©, les nouvelles requĂȘtes attendent. Surveillez la profondeur de file et le TTFT, pas les vibes.
Fixez aussi des limites en amont : un reverse proxy avec plafond de connexions Ă©choue vite et honnĂȘtement, lĂ oĂč une file profonde Ă©choue lentement et mystĂ©rieusement.
Planification de capacité, en gros
Ce qu'une requĂȘte coĂ»te au-delĂ des poids, c'est le cache KV, par jeton, pour tout son contexte :
octets KV/jeton â 2 Ă layers Ă kv_heads Ă head_dim Ă bytes_per_value
Exemple dĂ©taillĂ©, modĂšle dense 8B typique (32 couches, 8 tĂȘtes KV, dimension de tĂȘte 128, valeurs fp16) : 2 Ă 32 Ă 8 Ă 128 Ă 2 B â 131 KB par jeton â une conversation de 2k jetons â 256 MiB de KV â dix tels chats â 2.5 GB par-dessus les ~5 GB de poids.
(le 2 est pour K et V ; voir cache KV). Les agents Ă long contexte sont donc bien plus chers par requĂȘte que le chat. Tableau de confort approximatif, fortement prudent â contextes de longueur chat, ordre de grandeur seulement :
| GPU | ModÚle | Chats légers simultanés approximatifs |
|---|---|---|
| 8 GB | 7â8B Q4 | 1â3 |
| 24 GB | 8B Q4 | ~10â30 |
| 24 GB | 32B Q4 | ~3â8 |
| 48 GB | 70B Q4 | ~5â15 |
Mesurez avec vos vrais prompts : la longueur de contexte déplace ces chiffres plus que toute autre variable.
Signaux que vous ĂȘtes saturĂ©
- Le TTFT grimpe de millisecondes à des secondes au fil de la journée.
- Profondeur de file durablement au-dessus de zĂ©ro ; requĂȘtes en attente avant le premier jeton.
- tok/s par flux qui fléchit à mesure que les lots se serrent.
- Logs vLLM montrant prĂ©emption ou recalcul de KV â pression mĂ©moire, pas lenteur du modĂšle.
L'un de ceux-ci : plafonnez le contexte, quantifiez le cache KV, ou ajoutez du GPU â dans cet ordre de bon marchĂ© â avant que vos utilisateurs ne se plaignent fort.
Tracez le TTFT et la profondeur de file sur une journĂ©e â une montĂ©e rĂ©guliĂšre signifie capacitĂ©, une dent de scie signifie des rafales que vous pouvez absorber avec une file.
Louer vs acheter, esquissé
Ă ce jour, un GPU louĂ© de classe 24GB tourne Ă environ $0.50â2/heure, et une carte 24GB d'occasion coĂ»te quelques centaines de dollars â seuil de rentabilitĂ© vers 300â1,000 heures de gĂ©nĂ©ration rĂ©elle. Le local gagne sur la confidentialitĂ©, la latence et l'absence de limites de dĂ©bit (le cadrage dans pourquoi local) ; la location gagne sur la demande en rafales et les modĂšles de classe 80GB qu'aucune carte grand public ne tient (voir calcul de VRAM pour qui tient oĂč). La plupart des gens surestiment leurs heures â instruentez une vraie semaine avant de dĂ©cider.
Voir aussi : vitesse · cache KV · servir un endpoint · calcul de VRAM