Was passiert beim Laden eines LLMs wirklich? Von der Datei bis zum ersten Token
Warum der erste Start eines lokalen LLMs dauert und der zweite nicht: GGUF, mmap, Page Cache, VRAM-Transfer, Layer-Offload, KV-Cache und keep_alive Schritt für Schritt.
Von Niclas Hennrich · Veröffentlicht: · 12 Min. Lesezeit
Reality Check
Stand: September 2026
- Belegt
- 25 Aussagen
- Theorie
- 3 Aussagen
Kurz gesagt: Bevor ein lokales Sprachmodell das erste Wort schreibt, durchläuft es mehrere Stationen: Die Runtime liest das Inhaltsverzeichnis der GGUF-Datei, blendet die Gewichte per mmap in den Arbeitsspeicher ein, kopiert die Schichten für die Grafikkarte über PCIe in den VRAM und reserviert Platz für den Kontext. Wie lange das dauert, hängt vor allem davon ab, ob die Datei noch im Page Cache des Betriebssystems liegt — deshalb ist der zweite Start oft viel schneller als der erste.
Das kennt jeder, der mit Ollama oder llama.cpp arbeitet: Die erste Frage nach dem Hochfahren hängt spürbar, die zweite kommt sofort, und nach einer Kaffeepause wartet man unter Umständen wieder. Das folgt aus dem Weg, den ein Modell von der Datei bis zum ersten Token nimmt.
Wie viel Speicher ein Modell braucht, erklärt Wie viel RAM und VRAM braucht ein LLM?, und der Local-AI-Rechner rechnet es für dein Modell aus. Hier geht es um die Zeit dazwischen.
Die Stationen im Überblick #
| Station | Was passiert | Was bremst |
|---|---|---|
| 1. GGUF-Datei öffnen | Header und Metadaten lesen | kaum etwas, der Kopf ist klein |
| 2. Gewichte einblenden | mmap statt kompletter Kopie | Datenträger beim ersten Zugriff |
| 3. Page Cache | Betriebssystem behält gelesene Daten | freier RAM |
| 4. Transfer in den VRAM | GPU-Schichten über PCIe kopieren | PCIe-Bandbreite |
| 5. Layer-Offload | Aufteilung GPU/CPU festlegen | VRAM-Größe |
| 6. KV-Cache reservieren | Platz für den Kontext anlegen | Kontextlänge |
| 7. Warm halten | Modell bleibt geladen oder wird entladen | Leerlaufzeit |
| 8. Prefill | Eingabe verarbeiten, erstes Token | Prompt-Länge |
Station 1: Die GGUF-Datei — Inhaltsverzeichnis vorne, Gewichte hinten #
Ein lokales Modell liegt meist als eine einzige .gguf-Datei vor. Was die
Quantisierungsstufen im Dateinamen bedeuten, erklärt
Quantisierung und GGUF. Für das Laden ist
etwas anderes wichtig: wie die Datei innen aufgebaut ist.
Laut Spezifikation beginnt eine GGUF-Datei mit einem kurzen Header — der Kennung „GGUF“, einer Versionsnummer sowie der Anzahl der Tensoren und der Metadaten-Einträge. Danach folgen die Metadaten als Schlüssel-Wert-Paare, dann für jeden Tensor Name, Dimensionen, Datentyp und Position in der Datei, und erst ganz am Ende die eigentlichen GewichtsdatenBelegt. Ein Tensor ist hier einfach ein mehrdimensionales Zahlenfeld, etwa die Gewichtsmatrix einer Schicht.
Die Runtime muss also nur den vorderen Teil lesen, um zu wissen, was sie vor
sich hat: Architektur, Anzahl der Schichten, maximale Kontextlänge und wo
jeder Tensor liegt. Zu den
Metadaten gehören etwa general.architecture sowie bei Llama-Modellen
llama.context_length und llama.block_countBelegt, also die
Kontextlänge und die Zahl der Transformer-Blöcke.
Das Format ist auf schnelles Laden ausgelegt. Die Spezifikation nennt „mmap compatibility“ ausdrücklich als Designziel; vor den Gewichtsdaten wird deshalb auf ein festes Vielfaches aufgefüllt, standardmäßig 32 ByteBelegt. Diese Ausrichtung sorgt dafür, dass Tensoren direkt aus der Datei benutzt werden können, ohne sie erst umzukopieren. Damit sind wir bei Station 2.
Station 2: mmap — einblenden statt einlesen #
Die naive Art, ein Modell zu laden, wäre: Datei komplett in den Arbeitsspeicher kopieren, dann loslegen. Bei einer Datei von mehreren Gigabyte heißt das warten, bis das letzte Byte da ist.
Die Alternative heißt Memory Mapping. Der Systemaufruf mmap() legt eine neue Abbildung im
virtuellen Adressraum des Prozesses anBelegt: Die Datei erscheint für das
Programm so, als läge sie bereits im Speicher. Tatsächlich geladen wird ein
Teil erst, wenn das Programm zum ersten Mal darauf zugreift. Diesen Moment
nennt man Page Fault — das Betriebssystem merkt, dass die angefragte Seite
(ein kleiner Speicherblock) fehlt, und holt sie nach. Die Manpage beschreibt mit MAP_POPULATE eine Option, die
die Datei vorab einliest („read-ahead“), um spätere Blockaden durch Page
Faults zu verringernBelegt — ohne sie wird also bei Bedarf nachgeladen.
Ein Vergleich: Statt ein Buch vollständig abzuschreiben, bevor du anfängst zu lesen, legst du das Original auf den Tisch und schlägst die Seite auf, die du gerade brauchst.
llama.cpp nutzt das standardmäßig. Die Doku älterer Versionen formuliert es so: Modelle werden per Voreinstellung in den Speicher eingeblendet, sodass das System nur die jeweils benötigten Teile lädtBelegt.
Die Schalter: früher --no-mmap und --mlock, heute --load-mode #
Viele Anleitungen im Netz nennen zwei Optionen. In älteren llama.cpp-Versionen (etwa Release b6000)
schaltet --no-mmap das Einblenden ab, --mlock hält das Modell im
Arbeitsspeicher fest, damit es nicht ausgelagert wirdBelegt. In der
aktuellen Doku gibt es diese beiden Schalter nicht mehr als eigene Optionen.
Stattdessen wählt
--load-mode (kurz -lm) zwischen auto (mmap, sofern alle Geräte es
unterstützen), none, mmap, mlock, mmap+mlock und dio für Direct
I/OBelegt. Die Abwägungen sind geblieben:
- Ohne mmap (
none): Laut Doku lädt das Modell langsamer, es kann aber seltener ausgelagert werden, wenn man kein mlock nutzt. Ist das Modell größer als der gesamte RAM, lädt es ohne mmap überhaupt nichtBelegt. - mlock: Das Modell wird im Speicher festgehalten und nicht ausgelagert. Das kann die Leistung verbessern, kostet aber einen Teil der mmap-Vorteile: Es braucht mehr RAM, und der Start kann länger dauern, weil das Modell vollständig in den RAM geladen wirdBelegt.
Die Voreinstellung passt in den meisten Fällen. mlock lohnt sich eher,
wenn andere Dienste auf demselben Rechner Speicher beanspruchen und das
Modell sonst verdrängt würde. Welche Schalter deine Version kennt, zeigt
llama-server --help.
Station 3: Der Page Cache — warum der zweite Start schneller ist #
Jetzt kommt der Teil, der die meisten Überraschungen erklärt. Linux behält
Dateiinhalte, die einmal gelesen wurden, im Arbeitsspeicher.
Die Manpage zu
/proc/meminfo beschreibt den Wert „Cached“ als Zwischenspeicher im RAM für Dateien, die
vom Datenträger gelesen wurden — den Page CacheBelegt.
Wird ein Modell per mmap eingeblendet, landen die gelesenen Teile in genau diesem Cache. Beendest du das Programm, verschwinden sie nicht sofort, sondern bleiben dort, bis der Speicher für etwas anderes gebraucht wird. Die llama.cpp-Doku nennt genau diesen Fall: Ein Modell kann bereits im Page Cache liegen, etwa wegen eines früheren LaufsBelegt. Beim nächsten Start kommt es dann aus dem RAM statt von der SSD.
Daraus folgt die typische Beobachtung: Der erste Start nach dem Booten ist durch die Lesegeschwindigkeit des Datenträgers begrenzt, jeder weitere Start durch den deutlich schnelleren ArbeitsspeicherEvidenz: Theorie. Wie groß der Unterschied ist, hängt von SSD, RAM und Modellgröße ab; eigene Messwerte dazu haben wir noch nicht.
Auch die Anzeige von free -h wird damit verständlicher. Nach einem
Modellstart scheint der RAM „voll“ — aber zu einem großen Teil mit Cache.
Die Spalte available schätzt,
wie viel Speicher für neue Programme verfügbar ist, ohne auszulagern, und
berücksichtigt dabei den Page CacheBelegt. Diese Spalte ist die
ehrlichere Zahl.
Wer einen echten Kaltstart nachstellen will, etwa um Datenträger zu vergleichen, kann den Cache als root leeren:
# Page Cache, Dentries und Inodes verwerfen (nur zum Testen)
echo 3 > /proc/sys/vm/drop_cachesLaut Kernel-Doku verwirft das nur „saubere“, also unveränderte Cache-Inhalte und zerstört keine Daten. Es kann aber spürbar Leistung kosten, weil alles erneut gelesen werden muss; außerhalb von Test- und Debugging-Umgebungen rät die Doku davon abBelegt. Auf einem Server mit laufenden Diensten also nicht einfach nebenbei ausführen.
Station 4: Über PCIe in den VRAM #
Solange das Modell nur im RAM liegt, rechnet höchstens die CPU damit. Soll die Grafikkarte arbeiten, müssen ihre Schichten in den Grafikspeicher (VRAM). Dieser Weg führt über PCIe, die Steckverbindung zwischen Mainboard und Karte.
Die Größenordnungen unterscheiden sich stark: Grafikkarten für Endkunden erreichen im eigenen Speicher Bandbreiten von einigen hundert bis über tausend GB/s, PCIe 4.0 liefert zwischen Rechner und Karte höchstens 32 GB/sBelegt.
Eine Rechnung, keine Messung: 8 GB Gewichte über 32 GB/s zu schicken, dauert rein rechnerisch 8 / 32 = 0,25 Sekunden — eine theoretische Untergrenze. In der Praxis kommen Protokoll-Overhead, die tatsächlich ausgehandelte PCIe-Generation und Lane-Zahl sowie der Weg vom Datenträger dazu. Beim Kaltstart dürfte deshalb meist der Datenträger das langsamere Glied sein, nicht PCIeEvidenz: Theorie.
Einmal im VRAM angekommen, bleiben die Gewichte dort, solange das Modell geladen ist. Der PCIe-Transfer ist also eine Einmalzahlung beim Laden, keine Gebühr pro Token.
Station 5: Layer-Offload — wer rechnet welchen Teil? #
Passt das Modell nicht komplett in den VRAM, wird es aufgeteilt. Ein Sprachmodell besteht aus vielen gleich aufgebauten Schichten (Layers); einige liegen dann auf der GPU, der Rest bleibt im RAM und wird von der CPU berechnet.
In llama.cpp legt -ngl
(lang --n-gpu-layers) fest, wie viele Schichten höchstens im VRAM liegen:
eine feste Zahl, auto oder all; voreingestellt ist autoBelegt.
Zusätzlich gibt es --fit,
standardmäßig eingeschaltet, das nicht gesetzte Parameter so anpasst, dass
alles in den Gerätespeicher passt, mit einer Reserve von standardmäßig 1024
MiB pro GerätBelegt. Ein Beispiel:
# Alle Schichten auf die GPU, Kontext 8192 Tokens
llama-server -m modell.gguf -ngl all -c 8192Ollama entscheidet die Aufteilung selbst. Wie sie ausgefallen ist, verrät
ein Befehl: ollama ps zeigt in
der Spalte „Processor“ entweder 100% GPU, 100% CPU oder eine Aufteilung
wie 48%/52% CPU/GPUBelegt. Steht dort eine Aufteilung, rechnet ein Teil
des Modells auf der CPU, und die Generierung wird deutlich langsamer. Wie
stark, zeigt ein Beispiel im Artikel
Tokens pro Sekunde: Was der Wert bei lokalen LLMs wirklich bedeutet.
Station 6: Der KV-Cache — Platz für den Kontext #
Bevor das Modell die erste Eingabe sieht, braucht es noch Arbeitsspeicher für den Kontext. Der KV-Cache speichert für jedes bereits verarbeitete Token Zwischenergebnisse der Attention-Berechnung, damit das Modell sie nicht bei jedem neuen Token neu ausrechnen muss.
Wie groß dieser Speicher wird, hängt an der eingestellten Kontextlänge.
Bei llama.cpp setzt -c
(lang --ctx-size) die Kontextgröße; der Standardwert 0 bedeutet, dass sie
aus dem Modell übernommen wirdBelegt — also aus dem Metadaten-Eintrag
von Station 1. Modelle mit sehr langem Trainingskontext belegen dann
entsprechend viel Speicher, auch wenn du nur kurze Fragen stellst.
Ollama nutzt laut FAQ
standardmäßig 4096 Tokens Kontext; ändern lässt sich das über
OLLAMA_CONTEXT_LENGTH oder den Parameter num_ctxBelegt.
Warum wird der Platz vorab festgelegt statt nach Bedarf? Weil es für die Rechenkerne einfacher ist, mit zusammenhängendem Speicher zu arbeiten. Die vLLM-Autoren beschreiben, dass bis dahin verbreitete Serving-Systeme für jede Anfrage einen zusammenhängenden Speicherblock in Höhe der maximalen Länge vorab reservierten — auch wenn die tatsächliche Anfrage viel kürzer warBelegt. Wie llama.cpp oder Ollama ihren KV-Speicher intern aufteilen, unterscheidet sich je nach Version; für dich zählt: Eine größere Kontextlänge kostet Speicher, schon beim Laden.
Das hat eine praktische Folge: Ein Modell, das mit 4096 Tokens Kontext
vollständig auf die GPU passt, kann bei einer deutlich größeren Kontextlänge
Schichten an die CPU abgeben müssen. Zum Sparen lässt sich bei llama.cpp der Datentyp des
KV-Caches mit --cache-type-k ändern, etwa von f16 (Standard) auf
q8_0Belegt. Wie viel das in Gigabyte ausmacht, rechnet der
Local-AI-Rechner.
Station 7: Warm halten mit keep_alive #
Ist das Modell geladen, bleibt die Frage: wie lange? llama-server kennt dafür --sleep-idle-seconds:
Nach der eingestellten Leerlaufzeit entlädt der Server Modell und KV-Cache
und lädt beides bei der nächsten Anfrage neu; voreingestellt ist die Funktion
ausBelegt. Ollama dagegen räumt von sich aus auf. Standardmäßig bleibt ein Modell 5 Minuten im Speicher und
wird dann entladen. Der Parameter keep_alive akzeptiert eine Dauer wie
"10m" oder "24h", eine Zahl in Sekunden, einen negativen Wert für
dauerhaftes Laden oder 0 für sofortiges Entladen nach der AntwortBelegt.
# Modell dauerhaft geladen halten
curl http://localhost:11434/api/generate -d '{"model": "llama3.2", "keep_alive": -1}'
# Modell sofort entladen
ollama stop llama3.2Global lässt sich der Standard
über die Umgebungsvariable OLLAMA_KEEP_ALIVE setzen; ein
keep_alive-Wert in der Anfrage überschreibt ihn. Ein Modell vorab laden
kann man mit einer leeren Anfrage an /api/generate oder /api/chatBelegt.
Das ist nützlich, wenn etwa ein Skript morgens das Modell anwärmt, bevor die
erste echte Frage kommt.
Die Abwägung: Ein dauerhaft geladenes Modell belegt VRAM, auch wenn es
niemand nutzt — auf einer Karte, die auch Transcoding oder andere Modelle
bedienen soll, ist das Platz, der fehlt. Kurzes keep_alive spart Speicher,
kostet aber nach jeder Pause wieder Ladezeit. Nach
dem Entladen können die Gewichte noch im Page Cache liegen; dann ist ein
erneutes Laden kürzer als ein echter KaltstartEvidenz: Theorie — solange der RAM
nicht anderweitig gebraucht wurde.
Station 8: Prefill und das erste Token #
Jetzt verarbeitet das Modell deine komplette Eingabe (Prefill) und erzeugt das erste Token — eine Wartezeit, die von Prompt-Länge und Rechenleistung abhängt, nicht mehr vom Laden. Mehr dazu im Artikel Tokens pro Sekunde: Was der Wert bei lokalen LLMs wirklich bedeutet.
Wenn das Laden lange dauert: Wo suchen? #
| Beobachtung | Wahrscheinliche Station | Was du prüfst |
|---|---|---|
| Nur der erste Start nach dem Booten ist langsam | Page Cache leer, Lesen vom Datenträger | Liegt das Modell auf einer SSD statt auf HDD oder Netzlaufwerk? |
| Nach jeder Pause wieder Ladezeit (Ollama) | keep_alive abgelaufen | Standard 5 Minuten, ggf. OLLAMA_KEEP_ALIVE erhöhen |
| Jeder Start langsam, obwohl RAM frei scheint | Cache wird verdrängt oder mmap aus | free -h → available; andere Speicherfresser; Lademodus |
| Modell lädt, antwortet aber zäh | Layer-Offload auf die CPU | ollama ps bzw. -ngl; Kontextlänge senken |
| Lädt gar nicht, Speicherfehler | Modell plus KV-Cache zu groß | Kontext kleiner, kleinere Quantisierung, Rechner nutzen |
Reality Check #
Stand September 2026:
- Belegt sind Aufbau von GGUF, mmap und Page Cache unter Linux sowie die Optionen von llama.cpp und Ollama, jeweils aus der offiziellen Doku. Die llama.cpp-Schalter haben sich zwischen Versionen geändert; Anleitungen im Netz können veraltet sein.
- Belegt ist auch die Größenordnung von PCIe 4.0 gegenüber dem Grafikspeicher. Die Rechnung zur Übertragungszeit ist eine theoretische Untergrenze, keine Messung.
- Nicht gemessen haben wir, wie viel schneller ein Warmstart aus dem Page Cache auf konkreter Hardware ist. Das hängt von Datenträger, RAM, Modellgröße und Runtime-Version ab; Zahlen aus fremden Setups übertragen wir bewusst nicht.
Was heißt das fürs eigene Homelab? #
Drei Dinge, die sofort helfen:
- Modelle auf die SSD. Beim Kaltstart ist der Datenträger das Nadelöhr. Ein Modellordner auf einer HDD oder einem Netzlaufwerk verlängert jeden ersten Start.
- RAM ist auch Ladezeit. Freier Arbeitsspeicher wird als Page Cache genutzt. Wer knapp kalkuliert, verliert den Warmstart-Vorteil, sobald andere Dienste den Cache verdrängen.
keep_alivebewusst wählen. Für einen Assistenten, den du ständig nutzt: lang oder dauerhaft. Für eine Karte, die sich mehrere Aufgaben teilt: kurz, und dafür die Ladezeit akzeptieren.
Dass bei lokaler KI eher das Bewegen von Daten als das Rechnen selbst bremst, zieht sich durch die ganze Hardwarefrage — vom Laden bis zu jedem einzelnen Token. Warum das so ist, beschreibt Warum kostet lokale KI so viel Hardware?, und wohin sich Rechnerarchitekturen deshalb entwickeln, zeigt Was kommt nach CPU und GPU?.
Eigene Messungen zu Kalt- und Warmstart gibt es bei LabKompass noch nicht; sie gehören ins LAB, sobald unser LLM-Benchmark steht.
Quellen
Offizielle Dokumentation
GGUF — Dateiformat-Spezifikation (docs/gguf.md) (externer Link, neues Fenster) — ggml-Projekt
Offizielle Dokumentation
mmap(2) — Linux manual page (externer Link, neues Fenster) — Linux man-pages project
Offizielle Dokumentation
proc_meminfo(5) — Linux manual page (externer Link, neues Fenster) — Linux man-pages project
Offizielle Dokumentation
free(1) — Linux manual page (externer Link, neues Fenster) — procps-Projekt
Offizielle Dokumentation
Documentation for /proc/sys/vm/ (drop_caches) (externer Link, neues Fenster) — Linux-Kernel-Dokumentation
Offizielle Dokumentation
llama.cpp — llama-completion-Dokumentation (tools/completion/README.md) (externer Link, neues Fenster) — llama.cpp-Projekt
Offizielle Dokumentation
llama.cpp — llama-server-Dokumentation (tools/server/README.md) (externer Link, neues Fenster) — llama.cpp-Projekt
Offizielle Dokumentation
llama.cpp — Dokumentation von llama-cli, Release b6000 (tools/main/README.md) (externer Link, neues Fenster) — llama.cpp-Projekt
Offizielle Dokumentation
Ollama — FAQ (externer Link, neues Fenster) — Ollama-Projekt
Originalpaper · 2026
Automated Tensor Scheduling for Hybrid CPU-GPU LLM Inference on Consumer Devices (externer Link, neues Fenster) — Liu et al.
Originalpaper · 2023
Efficient Memory Management for Large Language Model Serving with PagedAttention (externer Link, neues Fenster) — Kwon et al.
Häufige Fragen
- Warum startet ein lokales LLM beim zweiten Mal schneller?
- Beim ersten Start liest das Betriebssystem die Modelldatei vom Datenträger. Linux behält gelesene Dateiinhalte danach im Page Cache, einem Zwischenspeicher im freien RAM. Liegt das Modell dort noch, kommt es beim nächsten Start aus dem Arbeitsspeicher statt von der SSD. Die llama.cpp-Doku erwähnt ausdrücklich, dass ein Modell nach einem früheren Lauf schon im Page Cache liegen kann.
- Wie halte ich ein Modell in Ollama dauerhaft geladen?
- Ollama entlädt ein Modell standardmäßig nach 5 Minuten ohne Anfrage. Mit dem API-Parameter keep_alive lässt sich das ändern: eine Dauer wie "24h", ein negativer Wert wie -1 für dauerhaft oder 0 für sofortiges Entladen. Global setzt man den Standard über die Umgebungsvariable OLLAMA_KEEP_ALIVE, sofort entladen lässt sich ein Modell mit ollama stop.
- Was bedeuten --no-mmap und --mlock bei llama.cpp?
- Beide steuern, wie die Modelldatei in den Arbeitsspeicher kommt. Ohne mmap wird die Datei komplett eingelesen: laut Doku langsamer beim Laden, aber mit weniger Auslagerung, und bei Modellen größer als der RAM gar nicht möglich. mlock hält das Modell im RAM fest, damit es nicht ausgelagert wird, braucht dafür aber mehr Arbeitsspeicher. In aktuellen llama.cpp-Versionen heißen die Schalter --load-mode none, mmap, mlock oder mmap+mlock; ältere Versionen und viele Anleitungen nutzen noch --no-mmap und --mlock.
Teil des Themen-Hubs Lokale KI im Homelab · Abschnitt „Hardware verstehen“
Weiterlesen
KI & Local AI
Tokens pro Sekunde: Was der Wert bei lokalen LLMs wirklich bedeutet
Tokens pro Sekunde ist nicht gleich Tokens pro Sekunde: Prompt-Verarbeitung und Generierung verhalten sich grundverschieden. So liest du Benchmark-Angaben richtig.
KI & Local AI
Quantisierung und GGUF: Warum 14 GB Modell in 5 GB passen
Quantisierung macht lokale LLMs erst möglich: Was Q4_K_M, Q8_0 und GGUF bedeuten, wie viel Qualität bei welcher Stufe verloren geht und worin sich GGUF und Safetensors unterscheiden — einsteigerfreundlich erklärt für Ollama und llama.cpp.
KI & Local AI
Ollama einrichten: Lokale LLMs auf Server, PC und Mac
Ollama installieren und das erste lokale Sprachmodell betreiben — nativ auf Linux, als Docker-Container oder auf dem Mac. Mit Modellverwaltung, API-Grundlagen und dem Sicherheits-Kapitel, das viele überspringen: Ollama hat keine Authentifizierung.