VIBE CODING
GUIDE21 min read

Lokale LLM-Inferenz optimieren: Von 5 auf 100 Token/s mit llama.cpp

Lokale LLMs schneller machen: RAM-Takt, Quantisierung, KV-Cache, Layer-Placement und MTP-Decoding – die wirksamsten llama.cpp-Hebel nach Impact sortiert.

llama.cppLokale LLMsOpen SourcePerformance

Lokale LLM-Inferenz optimieren: Von 5 auf 100 Token/s mit llama.cpp

Lokale LLM-Inferenz heißt: Ein Sprachmodell läuft zu 100 % auf deiner eigenen Hardware — Prompts verlassen nie deinen Rechner. Homelab-Entwickler Kartikey Chauhan dokumentierte im Juni 2026, wie Gemma 4 26B auf einer RTX 4070 (12 GB) von 38,5 auf über 100 Token/s beschleunigt. Dieser Guide sortiert seine wirksamsten Hebel nach Impact — inklusive Vision, Multi-GPU und Quant-Messung.

Alle konkreten Messwerte stammen aus Chauhans Referenz-Setup: RTX 4070 (12 GB), Intel i5-12600K, 32 GB DDR5-6000, Linux mit CUDA und aktuellem llama.cpp-Build. Auf anderer Hardware verschieben sich die Zahlen, die Mechanik dahinter bleibt gleich. Zur Einordnung der Kosten: Hosted APIs liegen bei 1–15 US-Dollar pro Million Token, lokale Inferenz kostet Strom plus einmalig 500–3.000 US-Dollar Hardware — dafür gewinnst du Datenschutz, Offline-Betrieb und freie Modellwahl ohne Rate-Limits. Die meisten Power-User fahren zweigleisig: Cloud für Frontier-Aufgaben, lokal für alles Sensible und Experimentelle.

Was du brauchst

  • Eine GPU mit mindestens 8 GB VRAM (NVIDIA/CUDA für diesen Guide; AMD und Apple Silicon funktionieren mit anderen Backends)
  • 32 GB System-RAM oder mehr, wenn du MoE-Modelle mit CPU-Offload fahren willst
  • Linux bevorzugt (15–20 % schneller als Windows), Windows geht mit angepasstem Energieprofil
  • 2 Stunden Zeit für Build, Setup und erste Benchmarks

Die drei Kennzahlen: TTFT, PP und TG

Optimieren ohne Messen ist Stochern im Nebel. Lokale Inferenz hat drei Phasen mit unterschiedlichen Engpässen: TTFT (Time to First Token) — wie lange bis zur ersten Ausgabe. PP (Prompt Processing) — wie schnell das Modell deinen Input liest, GPU-limitiert. TG (Token Generation) — wie schnell die Antwort strömt, limitiert durch Speicherbandbreite. TG ist das, was du beim Arbeiten spürst.

TG-GeschwindigkeitGefühl
unter 5 Token/squälend, kaum nutzbar
5–10 Token/sfunktional — Lesegeschwindigkeit liegt bei ~7 Token/s
10–20 Token/sangenehm für interaktiven Chat
20–40 Token/sCoding-Agents fühlen sich flott an
über 40 Token/squasi instant

Zum Messen bringt llama.cpp eigene Werkzeuge mit: llama-bench für synthetische PP/TG-Benchmarks, llama-fit-params als Trockenlauf für die VRAM-Verteilung und llama-server mit Timing-Ausgabe im Log. Benchmarke immer bei der Kontextlänge, die du wirklich nutzt — kurze Test-Prompts verstecken KV-Cache-Kosten, Speicherwachstum in langen Sessions und die Kosten paralleler Slots.

Die Prioritäten-Checkliste: 10 Hebel nach Impact sortiert

Wer nur fünf Minuten hat, arbeitet diese Liste von oben ab — sie sortiert alle Maßnahmen dieses Guides nach typischem Effekt, gemessen auf dem RTX-4070-Referenzsystem:

#MaßnahmeTypischer Effekt
1XMP/EXPO im BIOS aktivierenbis zu 2–3× TG, wenn RAM auf Basistakt lief
2MTP-Speculative-Decoding2,0–2,6× TG bei Gemma 4 / Qwen 3.6
3QAT-Q4-Modelle statt PTQ-Q4Q8-nahe Qualität, ~20 % kleinere Datei
4Linux statt Windows (oder Energieprofil tunen)~15–20 % TPS
5tuned-ppd statt power-profiles-daemoneliminiert 20–30 % TG-Schwankung
6llama.cpp frisch aus Source bauenMoE-Kernel-Gewinne pro Release
7--fit on für VRAM-Placementmaximale GPU-Layer ohne Handarbeit
8KV-Cache auf q8_0halbiert KV-VRAM, +1–2 GPU-Layer
9--parallel 1 (Einzelnutzer)KV-VRAM zurück für Gewichte
10P-Core-Pinning per taskset+20–30 % TG auf Intel-Hybrid

Danach folgen Feinschliff-Maßnahmen: --flash-attn on (Pflicht für lange Kontexte), --no-mmap/--mlock, Headless-Betrieb, ubatch-Sweeps und N-Gram-Decoding für Code-Sessions.

Tool-Wahl: llama.cpp, Ollama, LM Studio oder vLLM?

llama.cpp ist das Werkzeug für maximale Kontrolle — jede Stellschraube in diesem Guide setzt darauf auf. Ollama nutzt llama.cpp intern, verdeckt aber genau die Flags, um die es hier geht: Layer-Placement, KV-Quantisierung und Batch-Größen sind dort nicht erreichbar. LM Studio bietet die beste Desktop-Oberfläche samt OpenAI-kompatiblem Endpoint inklusive Headless-Betrieb, JIT-Loading und Auto-Evict. vLLM zielt auf Multi-User-Serving mit voller VRAM-Bestückung und kontinuierlichem Batching — für Consumer-Hybrid-Setups ungeeignet. exllamav2 ist die schnellste Option für Dense-Modelle, die komplett ins VRAM passen (CUDA-only).

ToolStärkeSchwäche
llama.cppVolle Flag-Kontrolle, jede HardwareCLI-zentriert, Build nötig
OllamaZero-Config, Modellverwaltung, DockerKaum Tuning möglich
LM StudioGUI, Modell-Browser, lokale APIWeniger Detailkontrolle
vLLMProduktions-Serving, BatchingBraucht viel VRAM, nichts für Hybrid-Setups
exllamav2Maximaltempo für Dense-Modelle im VRAMCUDA-only, kein Offload
MLXApple Silicon, Unified MemoryNur macOS

Innerhalb von llama.cpp wählt das Backend die Hardware: CUDA für NVIDIA (am besten getestet), ROCm/HIP oder Vulkan für AMD, Metal automatisch auf macOS, SYCL für Intel Arc. Apple Silicon verändert die Größenrechnung komplett: CPU und GPU teilen sich denselben Speicherpool, ein Mac mit 128 GB RAM hat effektiv 128 GB "VRAM" bei ~400 GB/s Bandbreite (M3 Max).

Hardware-Basics: Speicher-Hierarchie schlägt alles

Token-Generierung ist bandbreitenlimitiert: Für jeden einzelnen Token müssen alle aktiven Gewichte durch den Speicher gestreamt werden. Die Hierarchie entscheidet, wie schnell das geht:

VRAM (GPU)                ~600–1.000 GB/s
Unified Memory (Apple)     ~200–400 GB/s
System-RAM                  ~50–200 GB/s   (Takt + Kanäle!)
NVMe-SSD                      ~5–7 GB/s
SATA-SSD / HDD              ~0,5–3 GB/s

Dense-Modelle (Gemma 4, Llama 3, Mistral) lesen pro Token alle Parameter — sie müssen für volles Tempo komplett ins VRAM. MoE-Modelle (Qwen3, DeepSeek, gpt-oss) aktivieren pro Token nur einen Bruchteil: gpt-oss-120b rechnet mit ~5B von 120B Parametern, Qwen3-Coder-Next mit ~3B von 80B. Deshalb dürfen Experten-Gewichte in den System-RAM ausweichen — und deshalb wird dessen Bandbreite zum Flaschenhals.

VRAMDense-ModelleMoE-Hybrid
8 GB7B–13B Q430B–70B mit viel RAM-Offload
12 GB13B–20B Q4, 7B Q870B–120B+ mit CPU-Offload
24 GB34B Q4, 13B Q8120B+ mit moderatem Offload
48 GB+70B Q8, 34B FP16Meiste MoE (fast) komplett auf GPU

Zwei Hardware-Tricks kosten nichts: Den Monitor an den Mainboard-Videoausgang (iGPU) statt an die Grafikkarte hängen — das gibt 500–1.000 MB VRAM frei, die sonst der Desktop frisst. Und bei Dense-Modellen komplett im VRAM ist die CPU fast arbeitslos; bei MoE-Hybrid rechnet sie dagegen jeden Token mit.

Hebel 1 — RAM-Takt: XMP aktivieren bringt bis zu 3× mehr Token

Der fieseste Standardfehler zuerst: Viele BIOS-Setups fahren RAM auf JEDEC-Basistakt statt auf dem beworbenen Profil. Auf Chauhans Maschine lief DDR5-6000 ohne XMP auf etwa einem Drittel der TG-Leistung — ein einziger BIOS-Schalter später war sie wieder normal. Bei MoE-Modellen mit RAM-Offload gibt es keinen anderen Hebel mit diesem Impact.

sudo dmidecode -t memory | grep -E "Speed|Configured"
# "Configured Memory Speed" muss dem XMP/EXPO-Profil entsprechen.
# Falls nicht: XMP (Intel) bzw. EXPO (AMD) im BIOS aktivieren.

Eine Minute Prüfzeit erspart hier Stunden Tuning an der falschen Stelle — deshalb steht dieser Check an Position 1.

Hebel 2 — llama.cpp selbst bauen statt Distro-Paket

Paketquellen liefern veraltete Builds, die nicht für deine GPU kompiliert sind. Die MoE-Kernel von llama.cpp werden mit praktisch jedem Release schneller — vor jedem Benchmark lohnt ein git pull plus Rebuild. Der CUDA-Build für eine RTX-40-Karte (Compute Capability 89):

git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DGGML_CUDA=ON \
  -DGGML_NATIVE=ON -DGGML_LTO=ON -DGGML_CUDA_GRAPHS=ON \
  -DGGML_CUDA_FA=ON -DGGML_CUDA_FA_ALL_QUANTS=ON \
  -DCMAKE_CUDA_ARCHITECTURES=89
cmake --build . --config Release \
  --target llama-server llama-bench llama-fit-params --parallel

Die Architektur-Nummer nicht blind übernehmen: 89 gilt für Ada/RTX 40, ältere Karten brauchen andere Werte (NVIDIA-Tabelle prüfen); bei gemischten Karten eine Semikolon-Liste wie "86;89" übergeben. AMD-GPUs bauen mit -DGGML_HIP=ON (ROCm) oder -DGGML_VULKAN=ON; für portable Binaries GGML_NATIVE abschalten oder mit -DGGML_BACKEND_DL=ON Backends zur Laufzeit laden. Ein Detail für später: GGML_CUDA_FORCE_CUBLAS klingt nach mehr Tempo, ist auf Consumer-Hardware aber langsamer als die GGML-eigenen MMQ-Kernel — Chauhan maß ~45 Token/s PP-Regression ohne TG-Gewinn.

Hebel 3 — Quantisierung: Q5 als Standard, QAT wenn verfügbar

Quantisierung reduziert die Gewichts-Präzision und damit Dateigröße und Speicherbedarf. Faustregel: die höchste Quantisierung nehmen, die ins VRAM+RAM-Budget passt. Q8_0 ist praktisch verlustfrei bei 65 % der FP16-Größe, Q5_K_XL ein starker Default bei ~40 %, Q4_K_M der übliche Kompromiss bei ~35 % — und Q2_K merklich degradiert.

QuantGröße vs. FP16Qualität
Q8_0~65 %praktisch verlustfrei
Q6_K~50 %nahezu verlustfrei
Q5_K_M / Q5_K_XL~40 %sehr nah an FP16 — starker Default
Q4_K_M / UD-Q4_K_XL~35 %guter Kompromiss
IQ3 / IQ4~25–35 %oft besser als ältere Quants gleicher Größe
Q2_K~25 %merklich schlechter
MXFP4 (nativ)~35 %besser als Q4_K_M — gpt-oss ist darin trainiert

Ein Sonderfall verdient Aufmerksamkeit: QAT (Quantization-Aware Training). Dabei lernt das Modell schon im Training mit Quantisierungsrauschen umzugehen, statt nachträglich gerundet zu werden. Chauhans Gemma-4-QAT-Tests zeigen 4-Bit-Verhalten nahe Q8-Qualität — und das 26B-Modell schrumpft von ~18 GB auf ~14,2 GB, wodurch deutlich mehr Layer direkt ins VRAM passen. Unsloth-Dynamic-Quants (UD-Präfix) verfolgen einen verwandten Ansatz beim Packen: empfindliche Tensoren behalten mehr Präzision, robuste werden stärker komprimiert. iMatrix- und IQ-Quants kalibrieren den Quantisierer an repräsentativem Text — wichtig zu wissen: Eine Wiki-Kalibrierung und eine Code/Chat-Kalibrierung schützen unterschiedliches Verhalten.

Quant-Qualität messen: Perplexity, KLD und die letzte Instanz

Dateigröße und Token/s sind leicht zu messen, Qualität nicht. Drei Metriken helfen bei der Vorauswahl, ersetzen aber keinen Praxistest. Perplexity (PPL) taugt als Rauchtest: Fällt ein Quant deutlich hinter gleich große Alternativen zurück, ist etwas kaputt — PPL kann aber Antwort-Flips verstecken, weil sich bessere und schlechtere Token-Wahrscheinlichkeiten ausmitteln. KLD (KL-Divergenz) vergleicht die Ausgabe-Verteilung des Quants mit dem Original und erwischt diesen Drift zuverlässiger; Unsloth stützt seine Dynamic-GGUF-Analysen darauf. Und selbst hohe Top-1-Übereinstimmung heißt nur "gleicher nächster Token wie die Referenz", nicht "faktisch richtig".

MetrikGut fürBlinder Fleck
Dateigröße / BPWPasst-es-PlanungSagt nichts über Qualität
PPLschneller Regressionstestübersieht Antwort-Flips
KLDVerteilungs-Drift vs. Originalhängt an Kalibrierdaten
Task-Evals (Aider, LiveCodeBench)Aufgaben-Nähelangsam, Template-fragil
Dein Workloaddie echte Antwortmusst du selbst fahren

Die Falle heißt Kalibrierungs-Overfit: Sehen iMatrix und Evaluation beide nach WikiText aus, glänzt ein Quant auf dem Papier und schwächelt bei Code, Chat oder Tool-Calls. Deshalb: nach Größe, PPL/KLD und Maintainer-Vertrauen vorsortieren — die finale Entscheidung fällt bei deiner Kontextlänge mit deinen Sampling- und KV-Einstellungen.

Hebel 4 — Layer-Placement: --fit, -ot und die Shared-Expert-Falle

Layer-Placement ist bei MoE-Modellen der größte Software-Hebel: möglichst viele Blöcke auf die GPU, Experten-Gewichte in den RAM. Drei Werkzeuge mit steigender Präzision: -ngl setzt die Zahl der GPU-Layer (99 = alles, runter bei OOM), --n-cpu-moe N legt die Experten der ersten N Layer auf die CPU, und -ot/--override-tensor platziert per Regex einzelne Tensoren:

# Alle Experten-Projektionen aller Layer auf die CPU:
--override-tensor ".ffn_(up|down|gate)_(ch|)exps=CPU"

Das (ch|) im Muster ist kein Tippfehler, sondern die Shared-Expert-Falle: Manche Modelle (Qwen3.5-122B, einige gpt-oss-Varianten) haben neben den gerouteten Experten (_exps) einen immer aktiven Shared Expert (_shexp) pro Layer. Ein Regex, das nur _exps trifft, lässt _shexp still im VRAM liegen — und produziert CUDA-OOM, das niemand versteht. Vorsicht auch bei --n-cpu-moe: Bei einem 60-GB-Modell alle Experten auf die CPU zu legen, versucht 60 GB in den RAM zu laden und legt einen 64-GB-Rechner hart lahm.

Bequemer ist --fit on: misst freies VRAM beim Start und berechnet die optimale Verteilung inklusive KV-Cache automatisch. llama-fit-params macht dasselbe als Trockenlauf und gibt die fertigen Flags aus — die hartkodierst du dann im Server-Skript. Faustregel: --fit on zum Experimentieren und nach Hardware-Wechseln, statisches Placement für den Dauerbetrieb. --fit-target nicht unter 512 MiB setzen: Der CUDA-Speicherpool wächst mit gefülltem Kontext, und zu wenig Reserve führt zu OOM mitten in der Session statt beim Start.

Hebel 5 — Kontext und KV-Cache: das VRAM-Budget verteidigen

Der KV-Cache speichert die Attention-Tensoren des bisherigen Kontexts, wächst linear mit und liegt im VRAM. Auf einer 12-GB-Karte frisst 128k-Kontext in f16 ganze 8 GB — es bleiben 4 GB für das Modell. Kontextwahl ist also Placement-Politik: Coding-Sessions fahren gut mit 64k, RAG braucht eher 128k+.

Kontextf16-KVq8_0-KV
8k~0,5 GB~0,25 GB
32k~2 GB~1 GB
64k~4 GB~2 GB
128k~8 GB~4 GB

Als konservative Baselines für einen Einzelnutzer-Server haben sich diese Profile bewährt — Startpunkte, keine Optimallösungen:

Workload--fit-targetKontextKV-Cache--parallelBatch
Text, 12 GB VRAM512 MiB64kq8_0/q8_011024
Text, 24 GB VRAM512–768 MiB128kq8_0/q8_01–21024
Vision, 12 GB VRAM2048 MiB64kq8_0/q8_01256
MTP-Speculative512+ MiB64kpro Modell testen11024

Vier Flags entscheiden das Budget. -ctk q8_0 -ctv q8_0 halbiert den KV-Cache praktisch verlustfrei — die frei gewordenen 2 GB bei 64k bedeuteten auf Qwen3-Coder zwei zusätzliche GPU-Layer und ~2 Token/s mehr TG (q4_0 nur unter extremem Druck: degradiert bei langem Kontext). --parallel 1 gilt für Einzelnutzer: Jeder Slot hält einen eigenen KV-Cache; der Schritt von 4 auf 1 Slot sparte bei gpt-oss-120b ~540 MiB — genug für einen weiteren GPU-Layer und +1 Token/s. --flash-attn on reduziert den Attention-Speicherverkehr und ist für stabile lange Kontexte Pflicht (auf CUDA ohne Nachteil; unter Vulkan treiberabhängig). Und --ctx-size ehrlich wählen statt maximal: Jedes ungenutzte Kontext-Gigabyte ist ein verschenkter GPU-Layer.

Batch-Größen: --ubatch-size ist kein Naturgesetz

Batch-Parameter steuern die Prefill-Phase. --batch-size (logischer Batch) bestimmt, wie viele Tokens pro Forward-Pass verarbeitet werden: 2048 für maximalen PP-Durchsatz, 1024 als Default, 512 bei knappem VRAM. --ubatch-size (physischer Micro-Batch, ≤ batch-size) legt fest, wie diese Arbeit gestückelt wird — größer kann PP beschleunigen, erhöht aber das VRAM-Maximum während des Prefills. Der Wert 512 ist ein sicherer Default, kein Gesetz:

for ub in 128 256 512 1024; do
  ./build/bin/llama-bench -m model.gguf \
    -p 2048 -n 128 -b 1024 -ub "$ub" \
    -ngl 99 -ctk q8_0 -ctv q8_0 -fa on
done

Die zwei besten Werte danach im echten llama-server gegentesten — Server-Speicherlayout, --parallel und Prompt-Cache verschieben das Ergebnis. Bei CUDA-OOM ausgerechnet während des Prefills zuerst --batch-size senken.

Sampling-Parameter: Modell-Defaults schlagen Bastelei

Sampling formt die Wahrscheinlichkeitsverteilung bei jedem Decode-Schritt und beeinflusst primär Qualität, kaum Tempo. Die wichtigste Regel steht in jeder Model-Card: Nimm die getesteten Defaults des Herstellers, bevor du experimentierst. Temperature 0.0 heißt deterministisch (gut für reproduzierbare Coding-Agents), 1.0 folgt der rohen Modellverteilung — darauf sind die meisten modernen Instruct-Modelle kalibriert. top-k 100 ist ein sicherer Performance-Deckel ohne messbaren Qualitätsverlust (auf gpt-oss-120b verifiziert). Und repeat-penalty gehört für Code auf 1.0: Code wiederholt naturgemäß Variablennamen und Keywords — wer das bestraft, verschlechtert die Ausgabe.

Modelltemptop-ktop-pmin-prepeat-penalty
Gemma 41.0640.950.01.0
Qwen3 / Qwen3-Coder1.0400.950.011.0
gpt-oss-120b1.01001.00.01.0

Hebel 6 — CPU-Kontrolle: P-Cores pinnen, Threads begrenzen

Intel-CPUs ab der 12. Generation mischen P-Cores und E-Cores — und E-Cores rechnen Matrix-Operationen deutlich langsamer. Landet der Inferenz-Prozess auf E-Cores, kostet das 20–30 % Token-Generierung bei MoE-Hybrid-Setups, wo die CPU jeden Token mitrechnet. Die Lösung ist ein Einzeiler:

taskset -c 0-11 llama-server ...   # i5-12600K: Kerne 0–11 sind P-Cores

Dazu --threads auf P-Core-Anzahl minus 1–2 setzen — mehr Threads als P-Cores verschlechtern das Ergebnis, weil alle um denselben Speicherbus konkurrieren. Für die Prefill-Phase darf --threads-batch dagegen die volle Thread-Zahl nutzen. Zwei Flags, die du dir sparen kannst: --poll ist bei Hybrid-CPU+GPU-Inferenz komplett wirkungslos (über mehrere Sweeps bestätigt — GPU-Kernel und PCIe dominieren die Synchronisation), und --numa bringt auf Single-Socket-Systemen nichts bis Gegenteiliges; das Thema wird erst auf Dual-Socket-Servern (EPYC, Xeon) real.

Speicher festnageln: --no-mmap und --mlock

Standardmäßig lädt llama.cpp Modelle per Memory-Mapping — elegant, aber bei MoE-Decode tückisch: Experten-Zugriffe sind nicht sequenziell, kalte Pages lösen ständig Page-Faults aus, und die TG-Rate zittert. --no-mmap lädt das komplette Modell vor Inferenzbeginn in den RAM; der Start dauert länger, dafür läuft jeder persistente Server ruhiger. --mlock pinnt die Modell-Pages zusätzlich gegen Swapping — wichtig, weil viele Distributionen vm.swappiness auf 60–150 mit ZRAM setzen. Ohne --mlock kann ein Swap-Ereignis mitten in der Session die Generierung scheinbar einfrieren. Abgerundet wird das Server-Profil mit --prio 2 (höhere Scheduling-Priorität gegen OS-Jitter) und --no-warmup (schnellerer Start; CUDA-Kernel kompilieren beim ersten echten Request).

Betriebssystem-Tuning: Linux schlägt Windows um 15–20 %

Linux liefert bei CUDA-Inferenz in der Praxis 15–20 % mehr Durchsatz: schlankerer Treiber-Overhead, besseres Scheduling unter Dauerlast, volle Kontrolle über CPU-Governor und Speicher. Unter Windows hilft das Energieprofil "Höchstleistung" plus "Prefer maximum performance" im NVIDIA-Panel; WSL2 kommt CUDA-seitig nah an nativ heran. Auf Linux lauert dafür eine besonders fiese Falle: KDE und GNOME installieren power-profiles-daemon, der auf manchen Boots einen gedrosselten Hardware-P-State setzt — alle sysfs-Checks melden brav "performance", trotzdem fehlen 20–30 % TG, mal ja, mal nein. Die Drosselung passiert auf MSR-Ebene, wo Standard-Tools nicht hinschauen. Der Fix:

sudo apt install tuned          # Ubuntu/Debian; ersetzt power-profiles-daemon
sudo systemctl enable --now tuned
sudo tuned-adm profile throughput-performance

Drei weitere Linux-Stellschrauben: Transparent Huge Pages auf always (echo always | sudo tee /sys/kernel/mm/transparent_hugepage/enabled), Headless-Betrieb per systemctl isolate multi-user.target (stoppt den Compositor, gibt 200–400 MB RAM plus Compositor-VRAM frei; zellij im TTY ersetzt die Fenster) — und der iGPU-Trick aus dem Hardware-Kapitel spart zusätzlich 500–1.000 MB VRAM.

Hebel 7 — Speculative Decoding: 2,6× schneller mit MTP

Speculative Decoding umgeht das Bandbreiten-Limit der Token-Generierung: Ein leichtes Draft-Modell rät mehrere Folge-Tokens, das Hauptmodell verifiziert sie in einem einzigen Forward-Pass. Modelle mit nativen Multi-Token-Prediction-Köpfen (Gemma 4, Qwen 3.6) bringen ihr Draft-Modell gleich mit — bei Gemma 4 26B ist es nur ~460 MB groß. Die Zahlen von der RTX 4070: Gemma 4 26B springt von 38,5 auf 100,6 Token/s (2,6×), das 12B-Modell erreicht 120,8 Token/s (2,0×).

llama-server -m gemma-4-26B.gguf \
  --spec-draft-model mtp-gemma-4-26B.gguf \
  --spec-type draft-mtp \
  --spec-draft-n-max 2      # 26B: 2; leichtere Modelle (12B): 4

Ein Fallstrick: Target- und Draft-KV-Cache sind getrennte Baustellen (-ctk/-ctv vs. -ctkd/-ctvd). Bei Gemma 4 drückte ein quantisierter Target-Cache die Draft-Akzeptanz gegen null — f16 kostete mehr VRAM, hielt die Akzeptanz aber über 70 % und war unterm Strich klar schneller. Rohe Token/s reichen als Messwert nicht; Akzeptanzrate immer mitloggen.

Für Coding-Sessions gibt es zusätzlich draftloses Speculative Decoding: N-Gram-Modi suchen wiederkehrende Token-Muster im Kontext — und Code wiederholt sich nun mal (Imports, Funktionsnamen, Boilerplate). --spec-type ngram-mod mit --spec-ngram-mod-n-match 24 ist der interessanteste Startpunkt für persistente Server; ngram-simple reicht für Einzel-Session-Tests. Beide lassen sich mit MTP kombinieren (--spec-type draft-mtp,ngram-mod) — aber nicht blind übernehmen: Lange Drafts verschwenden Arbeit, wenn die Akzeptanz schlecht ist. Messen, nicht glauben.

Coding-Agents lokal: diese Metriken zählen wirklich

Für Coding-Workloads ist TG nur die halbe Wahrheit. Agent-Loops lesen Dateien, feuern Tool-Calls und schieben immer wieder ähnlichen Kontext durch den Server — damit rücken TTFT, PP und der Prompt-Cache ins Zentrum: Startet die Ausgabe nach einem Tool-Call schnell? Verdaut der Server 8k–64k Code-Kontext ohne Gedenkpause? Greift der Prompt-Cache bei wiederholtem Agent-Kontext tatsächlich? Bleiben VRAM und RAM nach 30–60 Minuten Session flach? Ein brauchbarer Schnelltest in vier Akten: kalter Prompt nach Server-Start, gleicher Prompt mit warmem Cache, eine kleine Inspect-Edit-Explain-Schleife, ein langer Prompt nahe der echten Kontextgröße. Wer Profile veröffentlicht oder vergleicht, notiert mindestens: Modell, Quant, llama.cpp-Commit, Kommandozeile, Kontext, Batch/ubatch, KV-Präzision, PP, TG, TTFT, Draft-Akzeptanz und VRAM nach langer Session — "fühlt sich schnell an" ist kein Benchmark.

Vision-Modelle: der Projektor braucht eigenen Platz

Multimodale Modelle laden neben den Gewichten einen Projektor (--mmproj, typisch 1–3 GB VRAM), und genau der produziert die zwei klassischen Fehlerbilder auf knappen Karten. Fehlerbild eins: Crash beim Laden, weil ein alter Build oder ein ohne Projektor berechnetes statisches Placement die mmproj-Allokation nicht einplant — aktuelle llama.cpp-Builds rechnen sie in --fit ein, also Build aktualisieren und --fit mit Projektor laufen lassen. Fehlerbild zwei: Assertion beim ersten Bild, denn ein Bild tokenisiert zu mehreren hundert Tokens — ist --ubatch-size kleiner als die Bild-Token-Zahl, bricht llama.cpp ab. Deshalb --ubatch-size 512 oder höher. Chauhans stabiles 12-GB-Profil:

llama-server -m model.gguf --mmproj mmproj.gguf \
  --ctx-size 65536 --fit on --fit-ctx 65536 --fit-target 2048 \
  -ctk q8_0 -ctv q8_0 --flash-attn on \
  --batch-size 256 --ubatch-size 512 \
  --no-mmap --mlock --parallel 1

Die 2048 MiB Fit-Reserve sind bewusst großzügig; Text- und Vision-Server auf derselben GPU besser auf getrennten Ports fahren.

Multi-GPU: layer zuerst, tensor mit Vorsicht

llama.cpp verteilt Modelle mit drei Split-Modi auf mehrere Karten — und die langweilige Option gewinnt meistens. --split-mode layer legt zusammenhängende Layer-Gruppen auf verschiedene GPUs: kompatibelster Modus, erster Versuch, bei ungleichen Karten mit --tensor-split 3,1 gewichtbar (GPU 0 bekommt 75 %). row ist upstream veraltet — für neue Setups ignorieren. tensor (echtes Tensor-Parallel) kann die TG-Latenz bei Dense-Modellen mit schnellem Interconnect senken, hat aber harte Auflagen: viele MoE-Architekturen brechen mit "not implemented" ab, quantisierter KV-Cache wird nicht unterstützt (f16/bf16/f32 Pflicht), und --fit funktioniert nicht — Kontext, Slots und Layer verwaltest du selbst. GGML_CUDA_P2P=1 kann Peer-Transfers beschleunigen, auf manchen Systemen aber crashen oder Ausgaben korrumpieren: erst testen, dann behalten. Ist Multi-GPU langsamer als eine Karte, ist fast immer der Interconnect der Flaschenhals.

Am äußersten Rand der Tuning-Skala liegt der ik_llama.cpp-Fork von Ikawrakow: MoE-spezifische Kernel-Optimierungen (u. a. fusionierte MoE-Kernel) und oft die erste Adresse für neue IQ/K-Quant-Verfahren, besonders stark bei CPU- und Hybrid-MoE-Läufen. Nichts davon fließt upstream zurück — der Fork lohnt erst, wenn die Standard-Konfiguration ausgereizt ist.

Was tun, wenn es nicht funktioniert?

SymptomUrsacheFix
TG schwankt 20–30 % zwischen Bootspower-profiles-daemon drosselt HWPtuned-ppd + throughput-performance
TG stabil, aber weit unter SollXMP/EXPO aus, RAM auf BasistaktSpeicherprofil im BIOS aktivieren
TG niedriger als P-Core-BaselineE-Cores rechnen mittaskset -c auf P-Cores
OOM mitten in der Session--fit-target zu kleinauf ≥ 512 MiB erhöhen
Intermittierendes OOM bei langen PromptsGGML_CUDA_GRAPH_OPT=1auf 0 setzen; nur nach A/B-Test aktivieren
TG bricht nach Minuten einModell wird geswappt--mlock setzen, RAM prüfen
Vision-Modell crasht beim Ladenmmproj nicht eingeplantllama.cpp updaten, --fit mit mmproj
Vision-Assertion beim ersten Bild--ubatch-size < Bild-Tokens--ubatch-size 512 oder höher

Vor jedem Benchmark — und immer, wenn TG unerklärlich niedrig ist — lohnt die komplette Diagnose-Runde:

sudo dmidecode -t memory | grep -E "Speed|Configured"   # 1. RAM-Takt
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor        # 2. = performance
cat /sys/devices/system/cpu/cpu0/cpufreq/energy_performance_preference  # 3. = performance
grep "cpu MHz" /proc/cpuinfo | sort -rn | head -6       # 4. P-Cores nahe Max-Boost?
nvidia-smi | grep MiB                                   # 5. VRAM wirklich frei?
cat /sys/class/thermal/thermal_zone*/temp               # 6. Thermik (80000 = 80 °C)
ps aux --sort=-%cpu | head -10                          # 7. CPU-Fresser im Hintergrund
grep -E "pswpin|pswpout" /proc/vmstat                   # 8. Swap-Aktivität wächst?
nvidia-smi -q | grep -A 3 "PCIe Generation"             # 9. PCIe Gen 3/4?
sudo tuned-adm active                                   # 10. throughput-performance?

Punkt 3 ist der am häufigsten übersehene: Auf intel_pstate reicht der Governor allein nicht — auch die Energy Performance Preference muss auf "performance" stehen, nicht auf "balance_performance".

Sicherheit: llama-server gehört nicht ins offene Internet

Ein lokaler Inferenz-Server ist ein HTTP-Dienst wie jeder andere. llama-server, LM Studio und vergleichbare Gateways haben ohne Authentifizierung, Firewall und Rate-Limits nichts am offenen Internet verloren. Minimalstandard: an localhost binden, für LAN-Zugriff einen Reverse-Proxy mit Auth davorschalten, und für Remote-Zugriff ein privates VPN (Tailscale, WireGuard) statt eines offenen Ports. Modell-Dateien verdienen dieselbe Skepsis wie Software-Dependencies — Quelle, Lizenz und Datei-Hashes prüfen, bevor ein GGUF aus dritter Hand in den Autostart wandert. Prompts und Outputs können außerdem in App-Logs, Shell-History und Proxy-Logs landen; wer lokal aus Datenschutzgründen arbeitet, sollte diese Nebenkanäle mitdenken. Vertrauenswürdige lokale Agent-Workflows und alles, was andere Geräte erreichen können, gehören auf getrennte Endpoints.

Fazit: Erst messen, dann in dieser Reihenfolge drehen

Die Rangfolge der Hebel ist das eigentliche Ergebnis aus Chauhans Langzeit-Dokumentation, Stand Juni 2026: XMP/EXPO zuerst (bis 3×), dann MTP-Speculative-Decoding (2,0–2,6×), QAT-Quants, Linux statt Windows (15–20 %), frischer llama.cpp-Build, --fit on, KV-Cache auf q8_0, --parallel 1, P-Core-Pinning (20–30 %) und Flash Attention. Danach kommen die Feinheiten: ubatch-Sweeps auf der echten Prompt-Form, N-Gram-Decoding für repetitive Code-Sessions, GGML_CUDA_GRAPH_OPT nur nach A/B-Test. Wer die Liste von oben abarbeitet, statt an Sampling-Parametern zu spielen, holt aus einer 500-Euro-GPU mehr heraus als mancher aus der doppelt so teuren — und behält jeden Prompt im eigenen Netz. Für die Frage, wann sich das gegenüber Cloud-APIs rechnet, lohnt der Blick auf unsere Kosten-Analyse.

Häufige Fragen

Reicht Ollama, oder brauche ich wirklich llama.cpp?

Ollama nutzt llama.cpp intern, verdeckt aber fast alle Stellschrauben: Layer-Placement, KV-Cache-Quantisierung, Fit-Parameter und Batch-Größen sind dort nicht zugänglich. Für schnelles Ausprobieren reicht Ollama; wer das Maximum aus 12 GB VRAM holen will, kommt an llama.cpp mit eigenem Build nicht vorbei.

Warum ist mein MoE-Modell trotz guter GPU langsam?

MoE-Modelle streamen Experten-Gewichte aus dem System-RAM — der RAM-Durchsatz limitiert, nicht die GPU. Häufigste Ursache: XMP/EXPO ist im BIOS deaktiviert und der RAM läuft auf JEDEC-Basistakt. Das kostet bis zu zwei Drittel der Token-Generierung. Danach: E-Cores ausschließen und Layer-Placement mit --fit optimieren.

Wie viel VRAM brauche ich für ein 70B-Modell?

Dense 70B-Modelle brauchen für volle Geschwindigkeit ~48 GB VRAM (Q4). MoE-Modelle mit 70–120B Gesamtparametern laufen dank CPU-Offload schon auf 12-GB-Karten brauchbar, weil pro Token nur 3–5B aktive Parameter gerechnet werden — der Rest liegt im System-RAM.

Läuft das auch auf Apple Silicon oder AMD-GPUs?

Ja. Apple Silicon nutzt das Metal-Backend und Unified Memory — ein Mac mit 128 GB RAM hat effektiv 128 GB "VRAM" bei ~400 GB/s Bandbreite (M3 Max); dort lohnt der Vergleich mit dem MLX-Framework. AMD-GPUs laufen über ROCm/HIP oder Vulkan. Die CUDA-spezifischen Flags dieses Guides entfallen, die Konzepte (Quantisierung, KV-Cache, Placement) gelten überall.

Lohnt sich lokale Inferenz gegenüber Cloud-APIs?

Hosted APIs kosten 1–15 US-Dollar pro Million Token, lokale Inferenz nur Strom plus einmalig 500–3.000 US-Dollar Hardware. Lokal gewinnt bei Datenschutz, Offline-Betrieb und Experimenten; Frontier-Qualität für komplexe Agent-Aufgaben liefern weiterhin die großen API-Modelle. Die meisten Power-User fahren zweigleisig.

Quellen

  1. Local LLM Inference Optimization: The Complete Guide Kartikey Chauhan (carteakey.dev) (abgerufen 2026-07-16)
  2. llama.cpp – LLM inference in C/C++ ggml.org / GitHub (abgerufen 2026-07-16)
  3. Unsloth Dynamic 2.0 GGUFs Unsloth (abgerufen 2026-07-16)
+

Verwandte Artikel