Prefill vs. Decode: Warum LLM-Inference zwei Phasen hat

Automatische Übersetzung

Dieser Artikel wurde automatisch aus der englischen Originalversion übersetzt.

Prefill verarbeitet einen Prompt und erstellt dessen Attention-Cache. Decode nutzt diesen Cache, um weitere Tokens zu erzeugen. Langes oder gebündeltes Prefill kann große Matrixoperationen effizient nutzen; Decode mit kleinen Batches verbringt oft mehr Zeit damit, Weights sowie zwischengespeicherte Schlüssel und Werte zu lesen.

Diese Unterscheidung hilft Ingenieuren, einen langsamen ersten Token getrennt von der langsamen Generierung danach zu untersuchen.

Bestimme, welche Phase langsam ist

Gewöhnliches autoregressives Prefill erzeugt die Logits, aus denen der erste Ausgabe-Token gesampelt wird. Spätere Decode-Schritte fügen jeweils einen Token hinzu. Die Zeit bis zum ersten Token umfasst auch Wartezeit in der Warteschlange, Tokenization, Scheduling und Übertragung über das Netzwerk. Eine hohe TTFT beweist daher nicht, dass Prefill selbst langsam ist.

SymptomVor einer Änderung am Server messen
Der erste Token braucht bei längeren Prompts mehr ZeitWartezeit und Prefill-Dauer nach Eingabelänge
Spätere Tokens werden bei längeren Verläufen langsamerDecode-Zeit und Datenverkehr des KV cache
Ein langer neuer Prompt unterbricht andere StreamsScheduler-Iterationen und Zeitabstände zwischen Tokens
Getrennte Server verbringen Zeit mit der ZustandsübertragungÜbertragene KV-Bytes, Bandbreite und Wartezeit

Prefill verwendet Weights für mehrere Prompt-Tokens wieder. Die Implementierung kann Matrixblöcke dennoch mehrfach laden; sie garantiert nicht, dass jeder Weight genau einmal aus HBM gelesen wird. Splitwise beschreibt, wie diese Phasen unterschiedliche Hardware-Ressourcen nutzen.

Was Prefill in Chunks verändert

Prefill in Chunks verarbeitet einen langen Prompt über mehrere Scheduler-Iterationen. Der dokumentierte Scheduler von vLLM berücksichtigt zuerst laufende Decode-Anfragen und nutzt das verbleibende Token-Budget der Iteration für Prefill. Die tatsächliche Chunk-Größe richtet sich nach dem verfügbaren Budget.

Das kann Unterbrechungen bestehender Streams verringern und zugleich die TTFT der neuen Anfrage erhöhen. Kleinere Chunks verursachen auch zusätzliche Scheduling-Arbeit und lesen früheren Cache-Zustand erneut. Sarathi-Serve untersucht diesen Zielkonflikt; die dort berichtete zusätzliche Prefill-Zeit von etwa 25% bei Chunks mit 512 Tokens wurde für Yi-34B mit Tensorparallelität von zwei gemessen.

Disaggregated Serving führt Prefill und Decode dagegen auf getrennten GPU-Pools aus. Damit lässt sich jede Phase unabhängig optimieren, aber der KV cache der Anfrage muss übertragen werden. Prüfe Übertragungskosten und Pool-Auslastung, bevor du dieses Design einsetzt. Chunking verändert den Scheduler; Disaggregation verändert auch Deployment und Kommunikation.

Engineering-Leitfaden: Prefill versus Decode enthält Zeitabläufe für beide Ansätze.