Tools/LLMOps & Evals
vLLM geprüft: Inferenz auf eigener Hardware
vLLM macht aus einem Hugging-Face-Checkpoint einen OpenAI-kompatiblen Server: Was PagedAttention und kontinuierliches Batching bringen und was der Betrieb kostet.
- Art
- Inference server
- Preis
- Apache-2.0
Balázs Csorba··11 Min. Lesezeit
- Self-hosted inference
- OpenAI API
- PagedAttention
- GPU serving
- LLM runtime

Das Wichtigste in Kürze
- vLLM ist die Standard-Engine für selbst gehostete Inferenz mit offenen Gewichten auf NVIDIA- und AMD-Hardware, gewählt wegen der Breite bei Modellen, Quantisierung und API-Abdeckung, nicht wegen der Geschwindigkeit.
- PagedAttention und kontinuierliches Batching sind der Grund für die Existenz; die belastbare Aussage ist, dass die paging-basierte Allokation die KV-Cache-Verschwendung von 60 bis 80 Prozent auf unter 4 Prozent senkte, nicht das 24-Fache im Durchsatz von 2023.
- Prefix-Caching ist standardmäßig aktiv und verkürzt nur den Prefill; Workloads mit langen, wiederholten Prompts profitieren am meisten, lange Generierungen ohne gemeinsames Präfix gar nicht.
- Der Produktionsfehler ist Preemption per Recompute bei zu kleinem KV-Cache; KV-Cache-Auslastung und die kumulative Preemption-Zahl beobachten, nicht den aggregierten Durchsatz.
- Ein Aufbau mit vier GPUs läuft als sechs Prozesse und braucht mindestens sechs physische CPU-Kerne, der häufigste Grund für enttäuschenden Durchsatz.
vLLM ist eine Open-Source-Inferenz-Engine, die aus einem Hugging-Face-Checkpoint einen HTTP-Server macht, der die OpenAI-API spricht. Sie ist die Schicht zwischen Modell und allem, was es aufruft, und ihre einzige Aufgabe ist, die GPU beschäftigt zu halten. Das Urteil vorab: auf NVIDIA- oder AMD-Hardware mit offenen Gewichten ist sie die Standardwahl, weil kein anderes Projekt so viel Fläche mit so wenig Klebercode abdeckt. Auf einem Laptop, auf einem reinen CPU-Host oder bei einem Modell und einem Nutzer ist sie weit zu viel Maschinerie.
Sie konkurriert in der Serving-Schicht, nicht in der Modell-Schicht. Die Alternativen sind SGLang, das den Großteil des Designs teilt; NVIDIAs TensorRT-LLM, das Breite gegen Spitzenwerte auf NVIDIA-Teilen tauscht; llama.cpp, das dort anfängt, wo vLLM aufgibt; und Hugging Face TGI, dessen letzte Release v3.3.7 vom Dezember 2025 ist. Sie ist zugleich der übliche Ersatz für eine gehostete API, denn derselbe OpenAI-Client, der einen Anbieter anspricht, lässt sich auf einen lokalen Prozess umbiegen.
Was es wirklich ist
Die Fakten, die bei der Wahl einer Serving-Engine zählen, alle aus der Projektdokumentation und nicht von einer Anbieterseite:
- Apache-2.0, ohne kostenpflichtige Stufe und ohne Control Plane beim Anbieter.
- Entstanden im Sky Computing Lab der UC Berkeley; die Dokumentation nennt mehr als 2.000 Mitwirkende und eines der aktivsten Open-Source-KI-Projekte.
- Mehr als 200 Modellarchitekturen auf Hugging Face, darunter Decoder-only, Mixture-of-Experts, hybride Attention, multimodale Modelle, Embedding-, Rerank- und Reward-Modelle.
- OpenAI-kompatibler Server plus Anthropic-Messages- sowie Cohere-Embed- und Rerank-Endpunkte, dazu Sprache und strukturiertes Output. Ein Modell pro Serverprozess.
- CUDA und ROCm als erste Klasse, Intel XPU und Google TPU unterstützt, Hardware-Plugins für Ascend NPUs, Gaudi, Spyre, Apple Silicon, MetaX und weitere.
- Quantisierung über FP8, NVFP4, MXFP4, INT8 und INT4 sowie GPTQ-, AWQ-, GGUF- und compressed-tensors-Checkpoints.
- Eine Minor-Release etwa alle zwei Wochen: v0.24.0 erschien am 29. Juni 2026, sechs Wochen nach v0.20.2 vom 10. Mai.
Wie es funktioniert
Zwei Ideen tragen den Großteil des Durchsatzes. PagedAttention legt den Key-Value-Cache in Blöcke fester Größe ab und bildet ihn über eine Block-Tabelle auf nicht zusammenhängenden GPU-Speicher ab, so wie ein Betriebssystem Seiten abbildet; das Paper von 2023 maß in früheren Systemen 60 bis 80 Prozent des KV-Cache als durch Fragmentierung und Überreservierung verschwendet, bei paging-basierter Allokation unter 4 Prozent. Kontinuierliches Batching nimmt danach bei jedem Decode-Schritt neue Anfragen an, statt zu warten, bis sich ein Batch füllt, und daher kommt der größte Teil der Latenzverbesserung.
Die V1-Engine, die V0 während 2025 ablöste, mischt Prefill und Decode im selben Schritt und gibt Decode Vorrang, damit ein langer Prompt den Streaming-Verkehr nicht mehr ausbremst. Chunked Prefill ist standardmäßig aktiv. Auch Prefix-Caching ist standardmäßig aktiv und hasht Token-Blöcke, sodass ein wiederholter System-Prompt nur einmal vorgeprefüllt wird; die Projektdokumentation weist ausdrücklich darauf hin, dass es nur den Prefill verkürzt und für das Decode nichts bringt, es also bei langen Generierungen ohne gemeinsames Präfix fast nichts kauft. Spekulatives Decoding steht über n-Gram-, EAGLE- und DFlash-Proposer bereit, nicht über ein eigenes kleines Draft-Modell.
Einen Server aufsetzen
Die Installation ist ein Befehl, die dokumentierte Plattform ist Linux mit Python 3.10 bis 3.13. Ein Modell zu serven sieht so aus:
uv venv --python 3.12 --seed
source .venv/bin/activate
uv pip install vllm --torch-backend=auto
# Prefix caching and chunked prefill are on by default in V1.
vllm serve Qwen/Qwen3-8B \
--served-model-name qwen3-8b \
--max-model-len 32768 \
--gpu-memory-utilization 0.9 \
--tensor-parallel-size 2 \
--api-key "$VLLM_TOKEN"Die Flags sind im Wesentlichen Kapazitätsentscheidungen. --max-model-len begrenzt den Kontext und damit den KV-Cache, den eine einzelne Anfrage halten kann; setze ihn auf den längsten Prompt, den das Produkt wirklich braucht, nicht auf das Modellmaximum. --gpu-memory-utilization ist der Anteil der VRAM, der im Voraus für Gewichte und Cache reserviert wird; was nach den Gewichten übrig bleibt, misst der Profiling-Durchlauf beim Start und wandert in Blöcke. -O0 bis -O3 steuern, wie hart die Engine kompiliert und CUDA-Graphen aufnimmt, mit -O2 als Standard; --enforce-eager überspringt beides. Das Ansprechen braucht keinen neuen Client:
from openai import OpenAI
client = OpenAI(
api_key="EMPTY",
base_url="http://localhost:8000/v1",
)
stream = client.chat.completions.create(
model="qwen3-8b",
messages=[
{"role": "system", "content": "Answer in one sentence."},
{"role": "user", "content": "Why beat a contiguous KV cache?"},
],
max_tokens=200,
temperature=0,
stream=True,
)
for chunk in stream:
print(chunk.choices[0].delta.content or "", end="", flush=True)Was die Durchsatzversprechen wert sind
Die berühmten Zahlen stammen aus dem Launch-Blog von 2023, nicht aus aktuellen Benchmarks: LLaMA-7B auf einer A10G und LLaMA-13B auf einer A100 40GB, mit aus dem ShareGPT-Datensatz gezogenen Anfragelängen, ergaben bis zu 24-mal den Durchsatz von Hugging Face Transformers und das 2,2- bis 3,5-Fache von TGI. Diese Werte sind inzwischen Geschichte statt Spezifikation, und das Belastbare daran ist die Speicherverschwendung, nicht die Vielfachen. Geändert hat sich, dass das Niveau gewandert ist: die ernstzunehmenden Wettbewerber haben alle Paged Caches und In-Flight-Batching übernommen. Die nützliche Frage ist deshalb nicht mehr, wer besser bündelt, sondern wer schneller tuned, patcht und Modelle ergänzt.
| Stellschraube | Was sie ändert | Wann sie drehen |
|---|---|---|
--max-model-len | Begrenzt den Kontext und damit den KV-Cache einer einzelnen Anfrage | Der längste reale Prompt liegt weit unter dem Modellmaximum |
--gpu-memory-utilization | Anteil der VRAM, der im Voraus für Gewichte und KV-Cache reserviert wird | Das Start-Log meldet wenige Blöcke, oder Anfragen werden verdrängt |
max_num_batched_tokens | Prefill-Tokens pro Schritt: kleine Werte begünstigen die Inter-Token-Latenz, große die Zeit bis zum ersten Token | Interaktiver Chat gegenüber Offline-Batch-Arbeit |
--tensor-parallel-size | Teilt die Gewichte auf mehrere GPUs und schafft so KV-Cache-Raum pro Karte | Das Modell passt nicht, oder der KV-Cache ist die engere Grenze |
-O0 bis -O3 | Kompilierung und CUDA-Graph-Aufnahme; -O2 ist der Standard | Die Startzeit zählt mehr als das Decode im Steady State |
--enforce-eager | Überspringt Kompilierung und Graph-Aufnahme vollständig | Entwicklungsschleifen oder die Messung, wie viel eines Bootvorgangs die Aufnahme ist |
Der Fehlermodus, der in der Produktion wirklich auftritt, ist Preemption. Wenn der KV-Cache nicht alle laufenden Sequenzen fasst, verdrängt vLLM Anfragen und berechnet sie aus dem Prompt neu, sobald Platz ist; im aggregierten Durchsatz fällt das kaum auf, in der Tail-Latenz dominiert es. V1 setzt standardmäßig auf Recompute statt Swap, weil Swap mehr kostete, das Gegenmittel ist also Kapazität und kein Flag.
Im Produktivbetrieb
Observability zuerst
Die Engine stellt einen Prometheus-Endpunkt unter /metrics mit dem Präfix vllm: bereit. Das Metrics-Design-Dokument ist ungewöhnlich explizit: Server-Level-Gauges sollen die Histogramme auf Request-Ebene erklären, und die Histogramme sind die Serien, auf die ein Operator alarmieren soll.
vllm:time_to_first_token_seconds— Prefill-Kosten, was ein Nutzer bei einem kalten Prompt spürtvllm:inter_token_latency_seconds— Decode-Geschwindigkeit, was ein Nutzer nach Beginn der Generierung spürtvllm:e2e_request_latency_seconds— die Serie, gegen die eine Timeout-Regel geschrieben gehörtvllm:kv_cache_usage_percundvllm:num_requests_running— Kapazität; wenn beide gleichzeitig am Limit stehen, wächst die Warteschlangevllm:prefix_cache_queriesgegenvllm:prefix_cache_hits— das Verhältnis zeigt, ob gemeinsame Prompts wirklich wiederverwendet werden und ob die Workload zur Engine passt
Prozesszahl und CPU
Ein Aufbau mit vier GPUs ist kein einzelner Prozess. V1 betreibt einen API-Server-Prozess, einen Engine-Core-Prozess und einen Worker-Prozess pro GPU, also sechs insgesamt für einen Knoten mit Tensor-Parallelität 4; ein Data-Parallel-Aufbau kommt obendrauf mit einem Koordinator. Der Tuning-Guide nennt als Untergrenze 2 plus N physische Kerne für N GPUs, weil der Engine Core eine Busy-Loop fährt und unter CPU-Hunger sichtbar leidet.
Sicherheitslage
Authentifizierung ist ein geteiltes Geheimnis. Das Flag --api-key oder die Umgebungsvariable VLLM_API_KEY schaltet eine Header-Prüfung ein und akzeptiert mehrere Schlüssel zugleich, damit sie rotiert werden können. Es gibt kein Nutzermodell, keine Quoten pro Mandant und keine Autorisierungsschicht; was den Port erreicht, darf die ganze GPU nutzen.
Wo es kratzt
Zuerst drei Dinge. Es ist ein GPU-Server, keine Universal-Laufzeit: das dokumentierte Ziel ist Linux mit CUDA oder ROCm, ein reiner CPU-Host oder eine Apple-Silicon-Maschine bedeutet ein anderes Projekt und ein anderes Modellformat. Die Startzeit ist real, weil das voreingestellte Optimierungsniveau das Modell kompiliert und CUDA-Graphen aufnimmt, und ein kalter Container kann Minuten im Compiler verbringen, bevor das erste Token kommt. Und die API ist OpenAI-geformt, nicht OpenAI-vollständig: der Parameter suffix wird nicht unterstützt, user wird ignoriert, und parallele Tool-Calls sind modellabhängig und bestenfalls vorhanden.
| Engine | Lizenz | Wo sie gewinnt | Was sie kostet |
|---|---|---|---|
| vLLM | Apache-2.0 | Breite: die meisten Architekturen, die weiteste Menge an Quantisierungen und Hardware-Zielen, eine API für Text, Embeddings, Rerank, Sprache und strukturiertes Output | Kompilierung und Graph-Aufnahme bei jedem Boot, ein Modell pro Server und eine Busy-Loop, die CPU dahinter braucht |
| SGLang | Apache-2.0 | Radix-artiges Prefix-Sharing und Wiederverwendung von Zustand über Turns, passend zu Agent- und Retrieval-Verkehr mit immer demselben langen Kontext | Kleinerer Modellzoo und dünnere Serving-Fläche außerhalb von Chat-Completions |
| TensorRT-LLM | Apache-2.0, nur NVIDIA-Stack | Spitzenwerte auf den neuesten NVIDIA-Teilen, FP4- und FP8-Kernels, native Integration mit Dynamo und Triton | Nur NVIDIA und ein Neubau, sobald sich Modell, Quantisierung oder GPU-Generation ändern |
| llama.cpp | MIT | CPU, Apple Silicon und Edge-Hardware, GGUF-Quantisierung, eine einzelne Binärdatei ohne Python-Laufzeit | Ein anderes Modellformat, eine schwächere Geschichte beim Batching, keine vergleichbare Fläche für Embeddings oder Rerank |
Für die meisten Teams ist der wahre Vergleich die erste Zeile gegen die zweite. vLLM und SGLang lösen dasselbe Problem mit denselben Primitive, beide Apache-2.0, beide OpenAI-kompatibel, und beide bedienen einen normalen Chat-Workload gut. Der Prefix-Baum von SGLang passt besser, wenn immer wieder derselbe lange Kontext getroffen wird; Modellabdeckung und Quantisierungsmatrix von vLLM passen besser, wenn neue Checkpoints schneller ankommen als sich Workloads wiederholen.
Urteil
vLLM ist das Werkzeug der Wahl per Voreinstellung, und der Grund ist keine rohe Geschwindigkeit, sondern Fläche: die meisten Modelle, die meisten Quantisierungsformate, die meisten Hardware-Ziele und eine API, die Completions, Chat, Embeddings, Rerank, Sprache und strukturiertes Output abdeckt. Die Kosten sind real und meist mühelos zu beheben. Die Startzeit ist einstellbar, Preemption ist ein Kapazitätsproblem und eine verhungerte CPU ist ein Deployment-Fehler. Keines davon ist ein Grund, etwas anderes zu wählen.
- Wählen, wenn offene Gewichte auf NVIDIA- oder AMD-GPUs serviert werden und die Workload gebündelt ist: viele gleichzeitige Anfragen statt einer nach der anderen.
- Wählen, wenn der Modellwechsel häufig ist, denn ein neuer Checkpoint läuft meist vor der Unterstützung der Alternativen.
- Wählen, wenn der umgebende Stack schon die OpenAI-API spricht, denn die Migration ist eine Base-URL.
- Nicht wählen für Laptop, Edge-Box oder Single-User-Werkzeug; llama.cpp oder eine MLX-Laufzeitumgebung erledigt das mit einem Bruchteil des Speichers.
- Nicht wählen, wenn ein Modell auf einer NVIDIA-Generation festgeschrieben ist und Spitzen-Token pro Sekunde das einzige Ziel ist, denn TensorRT-LLM gewinnt diesen Handel um den Preis der Bindung.
- SGLang vor der Festlegung benchmarken, wenn der Verkehr agentisch oder retrieval-lastig ist und Kontext stark wiederverwendet wird; die beiden liegen so nah beieinander, dass meist entscheidet, welches um drei Uhr nachts debugbar ist.
Quellen
- vLLM-Dokumentation
- Optimierung und Tuning der V1-Engine
- Architekturübersicht und Prozesslayout von V1
- Metrics-Design
- Automatisches Prefix-Caching und seine dokumentierten Grenzen
- Online-Serving und die HTTP-API-Fläche
- Inside vLLM: Anatomie eines hochdurchsatzigen Inferenzsystems
- vLLM: einfaches, schnelles und billiges LLM-Serving mit PagedAttention
- Release-Verlauf
Häufige Fragen
Ist vLLM schneller als SGLang oder TensorRT-LLM?
Nicht pauschal, und die meisten publizierten Vergleiche sind nicht vergleichbar. Der Launch-Blog von vLLM aus 2023 nennt bis zu 24-mal den Durchsatz von Hugging Face Transformers und das 2,2- bis 3,5-Fache von TGI, gemessen mit LLaMA-7B und LLaMA-13B bei aus dem ShareGPT-Datensatz gezogenen Anfragelängen. Das datiert vor dem Zugang der Wettbewerber zu Paged Caches; benchmarke die eigene Anfragelängenverteilung.
Brauche ich eine GPU für vLLM?
Linux mit CUDA oder ROCm ist das dokumentierte Ziel, mit Python 3.10 bis 3.13. Intel XPU und Google TPU werden separat unterstützt, Apple Silicon über ein anderes, auf MLX basierendes Projekt, nicht über vLLM selbst. Reine CPU-Inferenz ist das Terrain von llama.cpp.
Wie viel VRAM braucht vLLM?
vLLM reserviert einen konfigurierbaren Anteil der VRAM für Gewichte und KV-Cache, misst den Rest mit einem Profiling-Forward beim Start und meldet, wie viele Blöcke hineinpassen. Praktisch ist die Grenze meist das Modellgewicht in der gewählten Quantisierung; der Rest ist KV-Cache, und dessen Größe bestimmt die Parallelität.
Kann ein vLLM-Server mehrere Modelle hosten?
Nicht nativ. Ein Serverprozess hostet ein Modell zur Zeit, daher betreiben Multi-Modell-Setups einen Prozess pro Modell hinter einem Router oder nutzen Data-Parallelismus, um dasselbe Modell über mehrere GPUs zu replizieren. Ausnahme sind LoRA-Adapter: die lassen sich zur Laufzeit laden und entladen, laut Dokumentation nur für die lokale Entwicklung.
Wie bleibt vLLM-Ausgabe über Upgrades hinweg reproduzierbar?
Die Engine-Version pinnen, da Minor-Releases etwa alle zwei Wochen erscheinen, und --generation-config vllm setzen, damit der Server nicht generation_config.json aus dem Hugging-Face-Repository anwendet und die Sampling-Defaults still überschreibt. Für deterministische Läufe zusätzlich die Temperatur auf null setzen und die Modellrevision pinnen.