Ich habe ein kleines Problem mit Screenshots von lokalen LLM-Benchmarks: Meist zeigen sie eine grosse Zahl, die Einheit tok/s und gerade genug Kontext, um alle im Raum in die Irre zu führen.

Ein Modell kann einen langen Prompt schnell schlucken und beim Schreiben einer Antwort trödeln. Es kann sich im Einzelchat flott anfühlen und zusammenbrechen, sobald mehrere Menschen den Server treffen. Es kann auch in einer synthetischen Schleife glänzen, die mit dem Grund für den Hardwarekauf nichts zu tun hat.

Darum ist „mein Modell schafft 18 Tokens pro Sekunde“ kein Benchmarkergebnis. Es ist der Anfang eines Benchmarkergebnisses.

Inferenz hat zwei Jobs

Bei den autoregressiven Decoder-Modellen, die die meisten von uns lokal betreiben, hat jede Anfrage zwei unterschiedliche Phasen:

  1. Prompt-Verarbeitung oder Prefill: Das Modell liest die Eingabe und baut seinen KV-Cache auf.
  2. Textgenerierung oder Decode: Das Modell erzeugt die Antwort Token für Token und erweitert den Cache weiter.

Das offizielle Werkzeug llama-bench behandelt sie als getrennte Tests: pp für Prompt-Verarbeitung, tg für Textgenerierung und pg für die Kombination. Das ist keine Pedanterie der Tool-Autoren. Genau darum geht es. Dasselbe Werkzeug hat getrennte Tests, weil die Workloads nicht austauschbar sind.

Prompt-Verarbeitung beantwortet: Wie lange dauert es bis zum möglichen ersten Token? Generierung beantwortet: Wie schnell kommt die Antwort danach? Wer beides vermischt, produziert ein Ergebnis, das vor allem von einer willkürlich gewählten Prompt- und Antwortlänge abhängt.

Ein Benchmark mit nur einer Durchsatz-Zahl ist wie ein Autotest mit ausschliesslich Höchstgeschwindigkeit. Technisch eine Messung. Praktisch ein Ausweichen.

Die zwei Werte, die ich sehen will

Für einen interaktiven lokalen Assistenten will ich getrennt sehen:

  • Prompt-Durchsatz bei realistischen Eingabelängen;
  • Generierungs-Durchsatz bei realistischen Antwortlängen.

Danach will ich einen Ende-zu-Ende-Lauf mit exakter Anfrageform: Prompt-Tokens, erzeugte Tokens, Kontextgrösse, Batch-Grösse, Backend, Quantisierung und Wiederholungen. Ohne das ist eine Zahl Trivia.

llama-bench macht die Trennung explizit. Ein reiner Prompt-Test nutzt -p, ein reiner Generationstest -n, ein kombinierter Lauf -pg. Wiederholungen liefern Durchschnitt und Standardabweichung. Das ist eine deutlich bessere Basis als eine zufällig günstige Antwort zu stoppen, während der Rechner sonst nichts tut.

# Prompt-Verarbeitung bei kurzen, mittleren und langen Eingaben
llama-bench -m model.gguf -p 512,2048,8192 -n 0 -r 5

# Decode-Geschwindigkeit für eine brauchbare Antwortlänge
llama-bench -m model.gguf -p 0 -n 256 -r 5

# Wie sich eine echte Anfrage anfühlt
llama-bench -m model.gguf -pg 2048,256 -r 5

Die Befehle sind nicht magisch. Ihr Wert liegt darin, dass sie die Frage präzise machen.

Den Benchmark an die Arbeit koppeln

Unterschiedliche lokale Workloads bestrafen unterschiedliche Schwächen.

Chat- und Coding-Assistenten kümmern sich um die Pause vor dem ersten sichtbaren Token und um den Takt danach. Eine Maschine mit schnellem Decode, die einen langen Verlauf kaum eingelesen bekommt, fühlt sich kaputt an – selbst mit einer glänzenden Generierungszahl.

RAG, Dokumentenanalyse und grosse System-Prompts lasten die Prompt-Verarbeitung aus. Wenn die Arbeit mit mehreren tausend abgerufenen Tokens beginnt, ist ein Test mit Mini-Prompt Selbsttäuschung mit Stoppuhr.

Batch-Extraktion interessiert sich oft stärker für Gesamtdurchsatz als für die First-Token-Latenz eines Menschen. llama.cpp hat dafür einen eigenen Batch-Benchmark. Er trennt Prompt-Zeit von Generierung und testet parallele Sequenzen. Eine Einzelbenutzer-Schleife sagt nichts darüber aus, wie sich ein Server unter Last verhält.

Laufende Agenten brauchen alles davon plus Wiederholbarkeit. Ein Agent, der grosse Tool-Ergebnisse liest, eine kurze Aktion schreibt und wiederholt, ist weder reiner Chat noch Bulk-Generierung. Messen Sie die Schleife, die wirklich läuft.

Darum gibt es keine universelle „beste lokale Modellgeschwindigkeit“. Es gibt Modelle und Maschinen, die für eine klar benannte Anfrageverteilung schnell sind. Nervige Antwort? Ja. Trotzdem die ehrliche.

Was ein glaubwürdiges Ergebnis enthält

Ich würde jeden lokalen Benchmark ohne diese Angaben zurückweisen:

  • exakte Modelldatei und Quantisierung;
  • Inferenz-Engine und Backend;
  • Prompt- und Generationstoken;
  • Kontextfenster und Batch-Grösse;
  • Wiederholungen und Streuung;
  • Prompt-Verarbeitung, Decode oder Ende-zu-Ende;
  • Parallelität bei einer Serverbehauptung.

Noch eine Falle: llama-bench dokumentiert ausdrücklich, dass Tokenisierung und Sampling nicht gemessen werden. Das ist in Ordnung; es ist ein fokussierter Engine-Benchmark. Seine Zahl ist aber nicht die vollständige Wall-Clock-Erfahrung einer Anwendung. HTTP, Queueing, Prompt-Formatierung, Tokenisierung, Sampling, Streaming und Konkurrenzlast liegen ausserhalb dieser sauberen Zahl.

Missbrauchen Sie keine präzise Messung, nur weil sie angenehm unvollständig ist.

Eine Benchmark-Karte, der ich vertraue

Modell: <exakte GGUF-Datei und Quantisierung>
Engine/Backend: <exakter Build und Backend>
Kontext / Batch: <Werte>
Wiederholungen: 5

Prompt-Verarbeitung: 2'048-Token-Prompt, Mittelwert ± Standardabweichung
Generierung: 256-Token-Decode, Mittelwert ± Standardabweichung
Ende-zu-Ende: 2'048-Token-Prompt + 256-Token-Antwort, Wall-Clock Mittelwert ± Standardabweichung
Parallelität: 1 (oder klar angegebene Serverlast)

Diese Karte ist weniger aufregend als eine riesige tok/s-Grafik. Gut so. Sie ist wiederverwendbar, vergleichbar und schwer versehentlich zu verfälschen.

Ich argumentiere nicht gegen Tokens pro Sekunde. Ich argumentiere dagegen, so zu tun, als gäbe es nur eine Sorte. Prompt-Aufnahme und Token-für-Token-Decoding sind verschiedene Jobs. Ein brauchbarer Benchmark gibt beiden einen Wert.

Alles andere sind zwei Benchmarks im Trenchcoat.

Quellen