localaiforum
Connexion
Guide › Les fondamentaux

Préremplissage vs décodage : comment la génération s'exécute

Appuyez sur Entrée et la génération s'exécute en deux phases à la physique totalement différente. Le préremplissage traite tout votre prompt en une passe parallèle — gourmand en calcul, rapide par jeton, mais vous attendez la totalité avant le premier mot. Le décodage émet ensuite la réponse jeton par jeton — chaque étape relit pour ainsi dire tous les poids du modèle depuis la mémoire pour produire un seul jeton. « Premier jeton lent, puis ça défile » n'est pas une bizarrerie de votre installation ; ce sont ces deux phases.

Phase 1 : le préremplissage — le prompt

  • Tous les jetons du prompt traversent le modèle simultanément : de grandes multiplications matricielles parallèles, exactement ce pour quoi les GPU sont faits. L'utilisation est élevée ; les jetons par seconde sont élevés.
  • Vous le ressentez comme le temps jusqu'au premier jeton (TTFT) : le silence après avoir appuyé sur Entrée.
  • La passe remplit aussi le cache KV avec les vecteurs clé/valeur de chaque jeton du prompt — le brouillon que le décodage lira.
  • Prompts plus longs, TTFT linéairement plus long : gros prompts système, documents RAG et historique de conversation sont tous préremplis à chaque fois, sauf si votre moteur met les préfixes en cache.

Phase 2 : le décodage — la réponse

  • Un jeton par passe avant. Cette passe exige tous les poids ; produire un seul jeton signifie streamer le modèle entier depuis la VRAM.
  • Le plafond est la bande passante mémoire, pas le calcul : grossièrement, tok/s de décodage ≈ bande passante effective ÷ octets de poids. 8 GB de poids sur une carte à ~400 GB/s effectifs ≈ 50 tok/s au plafond.
  • C'est pourquoi la quantification accélère le décodage : moins de bits par poids signifie moins d'octets à streamer à chaque étape (voir vitesse).

Pourquoi cette asymétrie : le préremplissage traite des milliers de jetons par lecture de poids (matrices énormes, intensité arithmétique élevée — limité par le calcul), le décodage en traite exactement un (chaque octet de poids rapatrié pour un seul jeton — limité par la bande passante). Mêmes poids, goulots opposés.

total_time ≈ prompt_tokens / prefill_tok_s  +  output_tokens / decode_tok_s

Exemple détaillé

prompt:   1,000 jetons   préremplissage 2,000 tok/s → 0.5 s   (TTFT)
sortie:     300 jetons   décodage         40 tok/s → 7.5 s
total ≈ 8.0 s — 94% du temps écoulé est du décodage
  • La première demi-seconde a traité 1,000 jetons ; les 7.5 secondes suivantes en produisent 300. Même modèle, même GPU, différence de 50× — une phase différente, pas un effort différent.
  • 40 tok/s font à peu près 160 caractères anglais par seconde (≈4 caractères/jeton) : plus vite que quiconque ne tape, d'où la lecture confortable du streaming (jetons).
  • Les mêmes 40 tok/s en coréen font environ 40–60 caractères/s : débit de jetons identique, moins de texte par jeton.
  • La longueur de sortie est un réglage côté décodage : max_tokens plafonne la durée de génération, les séquences d'arrêt l'écourtent. Les deux changent le temps réel linéairement (paramètres moteur).
  • Le streaming change la perception, pas la physique : vous regardez le décodage se produire au lieu de l'attendre, aux mêmes 40 tok/s.

Exemple détaillé 2 : le cas RAG

prompt: 12,000 jetons (système + 20 fragments récupérés)  préremplissage 1,500 tok/s → 8.0 s
sortie:    500 jetons                                     décodage         40 tok/s → 12.5 s
total ≈ 20.5 s — le TTFT seul est 39% de l'attente

C'est la silhouette des installations locales gourmandes en récupération : des prompts énormes font « réfléchir » le modèle pendant des secondes avant de taper. Les remèdes, par ordre de levier :

  • Récupérez moins — le top 3–5 fragments bat habituellement le top 20 (RAG).
  • Gardez le prompt système stable pour que le moteur puisse réutiliser un préfixe en cache.
  • Élaguez l'historique : les anciens tours peuvent être résumés au lieu d'être rejoués en entier.

Le cache KV : le brouillon qui grossit

Sans cache, générer le jeton N recalculerait l'attention sur tous les N−1 jetons antérieurs depuis zéro — chaque étape refaisant un travail identique, coût total quadratique en longueur. À la place :

  1. Le préremplissage calcule les clés et valeurs de tous les jetons du prompt et les stocke une fois.
  2. Chaque étape de décodage ne calcule que la requête/clé/valeur du nouveau jeton et ajoute son K/V au cache.
  3. L'attention du nouveau jeton est sa requête multipliée scalairement par toutes les clés stockées.
  4. Un jeton décodé, dans l'ordre : l'embedder, exécuter les couches en lisant le cache, projeter vers le vocabulaire, échantillonner — ajouter son K/V, répéter.

Désormais chaque étape de décodage est linéaire en longueur de contexte (lire le cache) au lieu de quadratique (tout recalculer). Le prix, c'est le cache lui-même, qui grossit à chaque jeton :

KV bytes ≈ 2 × layers × kv_heads × head_dim × bytes_per_value × context

modèle de classe 8B (32 couches, 8 têtes KV, dimension de tête 128, FP16) :
  2 × 32 × 8 × 128 × 2 B ≈ 128 KiB par jeton
  → ~2.6 GB à contexte 20k, ~17 GB à contexte 128k

Ce cache concurrence les poids pour la VRAM — les chats à long contexte font planter des machines qui exécutent le même modèle sans souci avec des prompts courts (cache KV, calcul de VRAM).

Le traitement par lots change l'économie

Lire 8 GB de poids pour émettre un jeton est du gaspillage ; la même lecture peut servir plusieurs séquences à la fois. Groupez 8 requêtes en lot et un seul flux de poids produit 8 jetons — le débit grimpe presque linéairement jusqu'à saturation du calcul. C'est tout le truc derrière le service (servir un endpoint, concurrence). Seul sur un laptop, vous payez le plein tarif par jeton ; les serveurs l'amortissent entre utilisateurs simultanés.

Lire les compteurs

Compteur Phase Principal facteur
TTFT préremplissage longueur du prompt, calcul, hits de cache de préfixe
tok/s d'éval de prompt préremplissage calcul, taille de lot
tok/s de génération décodage bande passante mémoire, octets de poids, lot
Débit (req/s) les deux taille de lot, réutilisation du cache de préfixe, slots parallèles
Mémoire de contexte les deux octets KV par jeton, quantification du cache

Mesurez avant de régler : chaque moteur sérieux journalise les vitesses d'évaluation de prompt et de génération par requête. Une minute de journaux vous dit quelle phase dévore votre latence ; deviner, non.

Le réglage suit la phase : des prompts plus courts et le cache de préfixe corrigent le TTFT ; la quantification et des poids plus petits corrigent le décodage (paramètres moteur, dépannage).

Voir aussi : vitesse · cache KV · concurrence · jetons