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.
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-Geschwindigkeit | Gefühl |
|---|---|
| unter 5 Token/s | quälend, kaum nutzbar |
| 5–10 Token/s | funktional — Lesegeschwindigkeit liegt bei ~7 Token/s |
| 10–20 Token/s | angenehm für interaktiven Chat |
| 20–40 Token/s | Coding-Agents fühlen sich flott an |
| über 40 Token/s | quasi 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ßnahme | Typischer Effekt |
|---|---|---|
| 1 | XMP/EXPO im BIOS aktivieren | bis zu 2–3× TG, wenn RAM auf Basistakt lief |
| 2 | MTP-Speculative-Decoding | 2,0–2,6× TG bei Gemma 4 / Qwen 3.6 |
| 3 | QAT-Q4-Modelle statt PTQ-Q4 | Q8-nahe Qualität, ~20 % kleinere Datei |
| 4 | Linux statt Windows (oder Energieprofil tunen) | ~15–20 % TPS |
| 5 | tuned-ppd statt power-profiles-daemon | eliminiert 20–30 % TG-Schwankung |
| 6 | llama.cpp frisch aus Source bauen | MoE-Kernel-Gewinne pro Release |
| 7 | --fit on für VRAM-Placement | maximale GPU-Layer ohne Handarbeit |
| 8 | KV-Cache auf q8_0 | halbiert KV-VRAM, +1–2 GPU-Layer |
| 9 | --parallel 1 (Einzelnutzer) | KV-VRAM zurück für Gewichte |
| 10 | P-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).
| Tool | Stärke | Schwäche |
|---|---|---|
| llama.cpp | Volle Flag-Kontrolle, jede Hardware | CLI-zentriert, Build nötig |
| Ollama | Zero-Config, Modellverwaltung, Docker | Kaum Tuning möglich |
| LM Studio | GUI, Modell-Browser, lokale API | Weniger Detailkontrolle |
| vLLM | Produktions-Serving, Batching | Braucht viel VRAM, nichts für Hybrid-Setups |
| exllamav2 | Maximaltempo für Dense-Modelle im VRAM | CUDA-only, kein Offload |
| MLX | Apple Silicon, Unified Memory | Nur 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.
| VRAM | Dense-Modelle | MoE-Hybrid |
|---|---|---|
| 8 GB | 7B–13B Q4 | 30B–70B mit viel RAM-Offload |
| 12 GB | 13B–20B Q4, 7B Q8 | 70B–120B+ mit CPU-Offload |
| 24 GB | 34B Q4, 13B Q8 | 120B+ mit moderatem Offload |
| 48 GB+ | 70B Q8, 34B FP16 | Meiste 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.
| Quant | Größe vs. FP16 | Qualitä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".
| Metrik | Gut für | Blinder Fleck |
|---|---|---|
| Dateigröße / BPW | Passt-es-Planung | Sagt nichts über Qualität |
| PPL | schneller Regressionstest | übersieht Antwort-Flips |
| KLD | Verteilungs-Drift vs. Original | hängt an Kalibrierdaten |
| Task-Evals (Aider, LiveCodeBench) | Aufgaben-Nähe | langsam, Template-fragil |
| Dein Workload | die echte Antwort | musst 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+.
| Kontext | f16-KV | q8_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-target | Kontext | KV-Cache | --parallel | Batch |
|---|---|---|---|---|---|
| Text, 12 GB VRAM | 512 MiB | 64k | q8_0/q8_0 | 1 | 1024 |
| Text, 24 GB VRAM | 512–768 MiB | 128k | q8_0/q8_0 | 1–2 | 1024 |
| Vision, 12 GB VRAM | 2048 MiB | 64k | q8_0/q8_0 | 1 | 256 |
| MTP-Speculative | 512+ MiB | 64k | pro Modell testen | 1 | 1024 |
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.
| Modell | temp | top-k | top-p | min-p | repeat-penalty |
|---|---|---|---|---|---|
| Gemma 4 | 1.0 | 64 | 0.95 | 0.0 | 1.0 |
| Qwen3 / Qwen3-Coder | 1.0 | 40 | 0.95 | 0.01 | 1.0 |
| gpt-oss-120b | 1.0 | 100 | 1.0 | 0.0 | 1.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?
| Symptom | Ursache | Fix |
|---|---|---|
| TG schwankt 20–30 % zwischen Boots | power-profiles-daemon drosselt HWP | tuned-ppd + throughput-performance |
| TG stabil, aber weit unter Soll | XMP/EXPO aus, RAM auf Basistakt | Speicherprofil im BIOS aktivieren |
| TG niedriger als P-Core-Baseline | E-Cores rechnen mit | taskset -c auf P-Cores |
| OOM mitten in der Session | --fit-target zu klein | auf ≥ 512 MiB erhöhen |
| Intermittierendes OOM bei langen Prompts | GGML_CUDA_GRAPH_OPT=1 | auf 0 setzen; nur nach A/B-Test aktivieren |
| TG bricht nach Minuten ein | Modell wird geswappt | --mlock setzen, RAM prüfen |
| Vision-Modell crasht beim Laden | mmproj nicht eingeplant | llama.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
- Local LLM Inference Optimization: The Complete Guide — Kartikey Chauhan (carteakey.dev) (abgerufen 2026-07-16)
- llama.cpp – LLM inference in C/C++ — ggml.org / GitHub (abgerufen 2026-07-16)
- Unsloth Dynamic 2.0 GGUFs — Unsloth (abgerufen 2026-07-16)
Verwandte Artikel
LLM Fine-Tuning 2026: Strategien für maximale Geschwindigkeit
Entdecke 4 Open-Source-Tools für effizientes LLM Fine-Tuning 2026. Optimiere Qwen oder Llama mit Unsloth und DeepSpeed für maximale Performance und hohen Speed.
Was kostet Claude Code? Preise, Limits und Spartipps 2026
Claude Code kostet 20 bis 200 $ pro Monat oder läuft per API. Was die 5-Stunden-Fenster bedeuten, wie du Tokens sparst und was steuerlich gilt — Juli 2026.
KI-Code-Assistenten auf dem Mac: Claude Code & Codex in VS Code installieren
Ein ausführlicher Guide zur Installation und Einrichtung von Claude Code und Codex in Visual Studio Code auf macOS. Optimieren Sie Ihren Workflow mit KI-Unterst