Zum Inhalt springen
labkompass

Guides · KI & Local AI

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

11 Quellen · Was die Stufen bedeuten


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 #

StationWas passiertWas bremst
1. GGUF-Datei öffnenHeader und Metadaten lesenkaum etwas, der Kopf ist klein
2. Gewichte einblendenmmap statt kompletter KopieDatenträger beim ersten Zugriff
3. Page CacheBetriebssystem behält gelesene Datenfreier RAM
4. Transfer in den VRAMGPU-Schichten über PCIe kopierenPCIe-Bandbreite
5. Layer-OffloadAufteilung GPU/CPU festlegenVRAM-Größe
6. KV-Cache reservierenPlatz für den Kontext anlegenKontextlänge
7. Warm haltenModell bleibt geladen oder wird entladenLeerlaufzeit
8. PrefillEingabe verarbeiten, erstes TokenPrompt-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_caches

Laut 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 8192

Ollama 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.2

Global 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? #

BeobachtungWahrscheinliche StationWas du prüfst
Nur der erste Start nach dem Booten ist langsamPage Cache leer, Lesen vom DatenträgerLiegt das Modell auf einer SSD statt auf HDD oder Netzlaufwerk?
Nach jeder Pause wieder Ladezeit (Ollama)keep_alive abgelaufenStandard 5 Minuten, ggf. OLLAMA_KEEP_ALIVE erhöhen
Jeder Start langsam, obwohl RAM frei scheintCache wird verdrängt oder mmap ausfree -h → available; andere Speicherfresser; Lademodus
Modell lädt, antwortet aber zähLayer-Offload auf die CPUollama ps bzw. -ngl; Kontextlänge senken
Lädt gar nicht, SpeicherfehlerModell 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_alive bewusst 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

  1. Offizielle Dokumentation

    GGUF — Dateiformat-Spezifikation (docs/gguf.md) (externer Link, neues Fenster) — ggml-Projekt

  2. Offizielle Dokumentation

    mmap(2) — Linux manual page (externer Link, neues Fenster) — Linux man-pages project

  3. Offizielle Dokumentation

    proc_meminfo(5) — Linux manual page (externer Link, neues Fenster) — Linux man-pages project

  4. Offizielle Dokumentation

    free(1) — Linux manual page (externer Link, neues Fenster) — procps-Projekt

  5. Offizielle Dokumentation

    Documentation for /proc/sys/vm/ (drop_caches) (externer Link, neues Fenster) — Linux-Kernel-Dokumentation

  6. Offizielle Dokumentation

    llama.cpp — llama-completion-Dokumentation (tools/completion/README.md) (externer Link, neues Fenster) — llama.cpp-Projekt

  7. Offizielle Dokumentation

    llama.cpp — llama-server-Dokumentation (tools/server/README.md) (externer Link, neues Fenster) — llama.cpp-Projekt

  8. Offizielle Dokumentation

    llama.cpp — Dokumentation von llama-cli, Release b6000 (tools/main/README.md) (externer Link, neues Fenster) — llama.cpp-Projekt

  9. Offizielle Dokumentation

    Ollama — FAQ (externer Link, neues Fenster) — Ollama-Projekt

  10. Originalpaper · 2026

    Automated Tensor Scheduling for Hybrid CPU-GPU LLM Inference on Consumer Devices (externer Link, neues Fenster) — Liu et al.

  11. 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