Gleicher Name, neuer Digest: Wie Ollama ein Modell ablegt
Ollama lieferte Gemma 4 unter unverändertem Namen plötzlich in anderer Form aus: als 1162 einzelne Tensoren in NVFP4 für Apples MLX statt als eine GGUF-Datei in Q4_K_M. Was ein Manifest und ein Digest sind, wie die beiden Formate aufgebaut sind, wie Quantisieren funktioniert, und was eine eigene Messung über das Tempo sagt.
Am 28. Oktober 2026 meldete ein Wächter, der jeden Morgen die lokal genutzten
Modelle prüft, zwei Auffälligkeiten. Die Modelle gemma4:26b und gemma4:31b
hatten über Nacht einen neuen Digest bekommen, bei unverändertem Namen. Und
beide antworteten in seiner Funktionsprobe deutlich schneller als am Vortag:
das 26B in 11,0 statt 17,9 Sekunden, das 31B in 10,6 statt 24,1.
Ein Blick in die Ablage zeigte, dass sich mehr geändert hatte als eine Zahl. Jetzt bestand das 26B aus 1162 einzelnen Dateien, eine je Tensor, und lief über einen anderen Unterbau. Das Serverprotokoll von Ollama zeigt, was vorher da war. Am selben Nachmittag lud es die alte Fassung über llama.cpp, aus genau den Dateien, die die Registry heute als GGUF-Variante für alle anderen Rechner führt.
Dieser Beitrag geht der Sache von Grund auf nach. Er erklärt, wie Ollama ein Modell ablegt und was ein Digest und ein Manifest sind. Er vergleicht die beiden Formate, beschreibt, wie Quantisieren funktioniert, und misst das Tempo beider Varianten. Gemessen ist auf einem MacBook Pro mit M4 Max und 64 GB Arbeitsspeicher, mit Ollama 0.40.15, am 09.11.2026.
Ein Name zeigt seit Ende Oktober auf zwei Varianten
Der Befund in einem Satz: Ollama liefert Gemma 4 für Apple-Rechner neu verpackt und neu quantisiert aus, für alle anderen Rechner als GGUF-Datei in Q4_K_M. Beide Formen stehen unter demselben Namen. Welche ein Rechner bekommt, entscheidet Ollama beim Herunterladen.
| GGUF-Variante | MLX-Variante | |
|---|---|---|
| Rechenwerk (Runner) | llama.cpp | MLX |
| Format | GGUF, eine Datei für das Sprachmodell | safetensors, eine Datei je Tensor |
| Teile beim 26B | 6 | 1175, davon 1162 Tensoren |
| Teile beim 31B | 6 | 1248, davon 1236 Tensoren |
| Quantisierung | Q4_K_M | NVFP4, beim 26B teils MXFP8 |
| Größe 26B | 18,73 GB | 16,15 GB |
| Größe 31B | 20,39 GB | 19,42 GB |
| verlangt mindestens | Ollama 0.30.9 | Ollama 0.34.1 beim 26B, 0.31.0 beim 31B |
| bekommt | jeder Rechner außer Mac mit Apple-Chip | Mac mit Apple-Chip |
Quelle: eigene Auswertung der Manifeste aus der Registry (externe Seite, registry.ollama.ai) und der Ablage am Gerät, 09.11.2026.
Damit unterscheiden sich die Varianten in drei Dingen:
- in der Verpackung, also wie die Zahlen auf der Platte liegen,
- in der Quantisierung, also mit wie vielen Bit jede Zahl gespeichert ist,
- im Runner, dem Programmteil, das die Zahlen beim Antworten durchrechnet. Bei der einen Variante ist es llama.cpp, bei der anderen MLX, Apples eigenes Rechenframework für maschinelles Lernen.
Der Beitrag erklärt alle drei einzeln. Zuerst kommt die Ablage, denn an ihr lässt sich alles Weitere ablesen.
Ollama legt ein Modell ab wie ein Container-Image
Ollama verwaltet diese Teile so, wie Docker und andere Container-Werkzeuge ihre Images verwalten. Es übernimmt sogar deren Dateiformate. Das Prinzip hat drei Ebenen:
- Ein Name zeigt auf ein Manifest.
- Das Manifest zählt die Blobs auf.
- Jeder Blob ist eine Datei, deren Name ihre eigene Prüfsumme ist.
eigene Darstellung nach der Ablage am MacBook Pro, Ollama 0.40.15, Stand 09.11.2026
Der Name führt zu einer Manifest-Liste
Auf einem Mac liegen alle Modelle unter ~/.ollama/models. Der Name
gemma4:26b entspricht dort einem Eintrag im Ordner manifests-v2:
~/.ollama/models/manifests-v2/ollama.com/library/gemma4/26b
-> ../../../../blobs/sha256-ed3c4359df980cb0b74949ea6a8a5089a6ec87fbfe2bbe21d0529fc9f4c7013c
Der Eintrag ist ein symbolischer Verweis auf eine Datei im Ordner blobs. Sie
ist 470 Byte groß und vollständig lesbar:
{
"schemaVersion": 2,
"mediaType": "application/vnd.ollama.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:001e5dafc3c77684c2307ebc6ab8e336e10c9b18eca52acf547d72fc83c3ca8c",
"runner": "llamacpp",
"format": "gguf"
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:48eb98ec778c163d87f69d735fcdd79e345063af9af4685613fd018ae5debf5e",
"runner": "mlx",
"format": "safetensors"
}
]
}
Das ist eine Manifest-Liste. Sie nennt zwei Manifeste, je eines für eine Variante, und schreibt an jedes, welcher Runner es ausführt und in welchem Format es vorliegt. Das Vorbild ist der Image Index (externe Seite, github.com) der Container-Welt, dort wählt ein Rechner nach Prozessor und Betriebssystem die passende Fassung eines Images. Ollama wählt nach dem Runner. Im Quelltext (externe Seite, raw.githubusercontent.com) steht die Reihenfolge: Ein Mac mit Apple-Chip bevorzugt MLX, dann llama.cpp, dann Ollamas eigene Engine. Jeder andere Rechner bevorzugt llama.cpp. Dass auf Apple-Chips MLX vorn steht, kündigen schon die Release Notes zu 0.40 (externe Seite, github.com) an: Dort läuft jede Bauform, die MLX unterstützt, automatisch darüber.
Daneben steht unter manifests/registry.ollama.ai/library/gemma4/26b eine
zweite Datei mit dem vollständigen Manifest der gewählten Variante. Ollama
schreibt sie nach dem Herunterladen als Rückfall-Anker. Eine ältere Fassung,
die keine Manifest-Listen kennt, kann das Modell darüber laden. An die Layer
dieser Datei hängt Ollama außerdem die Manifest-Liste und das gewählte Manifest
an. So löscht die Speicherbereinigung der älteren Fassung diese beiden Blobs
nicht. Das steht im Quelltext der Manifestablage (externe Seite, raw.githubusercontent.com)
und im Quelltext des Servers (externe Seite, raw.githubusercontent.com). Ob
dieser Anker dauerhaft bleibt, sagt der Quelltext nicht. Für die Sicherungen,
die Ollama beim Aufrüsten älterer Modelle anlegt, sagen die
Release Notes zu 0.40.2 (externe Seite, github.com): Sie bleiben nur
vorübergehend auf der Platte, und eine künftige Fassung soll sie automatisch
entfernen.
Das Manifest zählt die Teile auf
Das Manifest der MLX-Variante ist 252.937 Byte groß, weil es 1175 Einträge hat. Sein Anfang:
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"digest": "sha256:3a77d9b825b3c48b651f4e52e2e17abf3f3ea96923972776ad8424dc089da0c5",
"size": 419
},
"layers": [
{
"mediaType": "application/vnd.ollama.image.tensor",
"digest": "sha256:1483d6c2dfab956ed72f3582b6a7230213e366a7c9661579e83202e7e9dadb8d",
"size": 761266456,
"name": "model.language_model.embed_tokens.weight"
}
]
}
Der Ausschnitt zeigt von den 1175 Einträgen unter layers nur einen. Das
Schema folgt der
Manifest-Spezifikation von Docker (externe Seite, github.com): ein Verweis
auf eine Konfiguration (config) und eine Liste von Schichten (layers). Jeder
Eintrag nennt einen Medientyp, eine Größe und einen Digest. Ollama ergänzt bei
Tensoren und JSON-Dateien das Feld name, das die Spezifikation für Schichten
nicht vorsieht. Außerdem nutzt es eigene Medientypen, und an ihnen lässt sich die
Art eines Teils ablesen:
| Medientyp | Inhalt | Zahl beim 26B (MLX) |
|---|---|---|
application/vnd.ollama.image.tensor | ein Tensor im Format safetensors, mit Namen | 1162 |
application/vnd.ollama.image.json | eine JSON-Datei des Herstellers, etwa tokenizer.json mit 32 MB | 10 |
application/vnd.ollama.image.template | die Gesprächsvorlage | 1 |
application/vnd.ollama.image.license | die Lizenz, hier Apache 2.0 | 1 |
application/vnd.ollama.image.params | voreingestellte Parameter | 1 |
Die GGUF-Variante kommt mit sechs Einträgen aus. Der Medientyp model steht
für das Sprachmodell (17,07 GB), projector für den Bildteil (1,19 GB) und
draft für ein kleines Entwurfsmodell (0,46 GB). Dazu kommen Vorlage, Lizenz
und Parameter. Ein klassisch abgelegtes Modell wie qwen3:30b hat sogar nur
fünf.
Der Config-Blob beschreibt das Modell
Der Eintrag unter config zeigt auf eine 419 Byte kleine Datei, die das Paket
als Ganzes beschreibt:
{
"model_format": "safetensors",
"generation_defaults": { "temperature": 1, "top_k": 64, "top_p": 0.95 },
"renderer": "gemma4",
"parser": "gemma4",
"requires": "0.34.1",
"capabilities": ["completion", "vision", "tools", "thinking"],
"draft": {
"model_format": "safetensors",
"architecture": "Gemma4AssistantForCausalLM",
"tensor_prefix": "draft.",
"config": "draft/config.json"
}
}
Der Ausschnitt lässt vier leere Felder weg. Vier Angaben darin erklären viel:
requiresnennt die älteste Ollama-Fassung, die das Paket ausführen kann. Beim Herunterladen liest Ollama zuerst den Config-Blob und vergleicht die Angabe mit der eigenen Fassung. Ist die eigene älter, bricht der Download mit einer Fehlermeldung ab, bevor die Teile des Modells geladen werden. So steht es im Quelltext (externe Seite, raw.githubusercontent.com) von 0.40.15.rendererundparserersetzen die Gesprächsvorlage. Beiqwen3:30bbaut eine 1506 Byte lange Vorlage den Text zusammen, den das Modell sieht. Bei Gemma 4 übernimmt das Programmcode in Ollama, und ein zweites Stück Code zerlegt die Antwort in Denkspur, Text und Werkzeugaufrufe. Die Vorlage im Paket ist dann wirkungslos. Sie besteht deshalb nur noch aus{{ .Prompt }}.capabilitiessagt, was das Modell kann: Text, Bilder, Werkzeuge und eine Denkspur. Die Denkspur ist voreingestellt eingeschaltet, das zeigtollama show.draftverweist auf ein zweites, kleines Modell im selben Paket. Seine Tensoren beginnen mit der Vorsilbedraft.und liegen zwischen denen des großen Modells. Wozu es dient, steht im Abschnitt über das Tempo.
Jeder Teil heißt nach seiner Prüfsumme
In der Container-Welt heißt diese Prüfsumme Digest. Die
OCI-Spezifikation (externe Seite, github.com) beschreibt ihn als
Kennung des Inhalts, gebildet als kollisionsresistente Prüfsumme über die
Bytes, und empfiehlt SHA-256. Geschrieben wird er als Verfahren, Doppelpunkt,
Summe: sha256:b507b9c2…. Ollama legt jeden Blob unter genau diesem Namen ab,
mit einem Bindestrich statt des Doppelpunkts. So steht es im
Quelltext der Ablage (externe Seite, raw.githubusercontent.com).
Am kleinsten Blob von Gemma 4 lässt sich das nachrechnen. Die Vorlage ist 13 Byte lang:
$ printf '{{ .Prompt }}' | shasum -a 256
b507b9c2f6ca642bffcd06665ea7c91f235fd32daeefdf875a0f938db05fb315 -
$ ls ~/.ollama/models/blobs/ | grep b507b9c2
sha256-b507b9c2f6ca642bffcd06665ea7c91f235fd32daeefdf875a0f938db05fb315
$ printf '{{ .Prompt }} ' | shasum -a 256
5b16913cae6cfcf7452f2c2707b065f75823a00e452913eaea74028d5d4dd85d -
Ein angehängtes Leerzeichen gibt eine Summe, die mit der ersten nichts mehr
gemein hat. Für die Manifeste gilt dasselbe. Ollama behandelt ein Manifest
selbst als Blob, und sein Digest ist die Prüfsumme über seine JSON-Bytes. Auch
die Manifest-Liste von oben heißt deshalb sha256-ed3c4359…, und
shasum -a 256 auf die Datei ergibt genau diese Zahl. Die Kennung, die
ollama list neben jedem Modell zeigt, sind die ersten zwölf Zeichen des
Digests der gewählten Variante, hier 48eb98ec778c.
Daraus folgt eine Kette. Der Name zeigt auf die Liste, die Liste nennt die Digests zweier Manifeste, jedes Manifest nennt die Digests seiner Blobs. Ändert sich irgendwo unten ein Byte, ändert sich der Digest dieses Blobs, damit der Text des Manifests, damit dessen Digest, damit der Text der Liste. Beim Herunterladen rechnet Ollama die Summe jedes geladenen Blobs nach. Stimmt sie nicht, löscht es die Datei und meldet einen Fehler. Dafür gibt es zwei Wege im Quelltext: einen für Modelle mit einzelnen Tensoren im Quelltext des Herunterladens (externe Seite, raw.githubusercontent.com) und einen für alle anderen im Quelltext des Servers (externe Seite, raw.githubusercontent.com). Ein Blob, der schon auf der Platte liegt, wird nicht noch einmal geladen und dabei nicht erneut geprüft. Ein Manifest prüft Ollama zusätzlich bei jedem Lesen von der Platte gegen seinen Digest, so steht es im Quelltext der Manifestablage (externe Seite, raw.githubusercontent.com).
Gleiche Teile liegen nur einmal auf der Platte
Weil der Name einer Datei aus ihrem Inhalt folgt, liegt gleicher Inhalt automatisch nur einmal vor. Ein Modell, das einen vorhandenen Blob braucht, verweist einfach auf dieselbe Datei. Am Gerät lässt sich das zählen:
| Varianten | gemeinsame Blobs | gemeinsame Größe |
|---|---|---|
| 26B MLX und 31B MLX | 322 | 1,20 GB |
| 26B GGUF und 31B GGUF | 2 (Vorlage, Parameter) | 77 Byte |
| 26B MLX und 26B GGUF | 1 (Vorlage) | 13 Byte |
Die beiden MLX-Varianten teilen sich unter anderem Teile des Bildverständnisses,
das Vokabular des Entwurfsmodells und die Lizenzdatei. Zwei Verpackungen
desselben Modells teilen sich fast nichts. Sogar die Lizenz liegt doppelt vor:
derselbe Text von Apache 2.0 mit 11.358 Byte in der GGUF-Variante und mit
10.170 Byte in der MLX-Variante. Gelöscht wird ein Blob erst,
wenn kein Manifest mehr auf ihn verweist. So steht es im
Quelltext (externe Seite, raw.githubusercontent.com) für den Befehl
ollama rm.
Ein neuer Digest meldet geänderte Bytes, den Grund zeigt das Manifest
Ein Name wie gemma4:26b ist in der Registry ein beweglicher Zeiger. Lädt
Ollama ihn neu herunter, zeigt er danach auf das, was die Registry jetzt unter
diesem Namen führt. Der Digest dagegen ist an einen Inhalt gebunden. Ein neuer
Digest bei gleichem Namen sagt deshalb nur, dass irgendwo ein Byte anders ist.
Dafür gibt es mehrere Gründe, und das Manifest zeigt, welcher vorliegt:
| Grund | was sich ändert | woran man es im Manifest erkennt |
|---|---|---|
| neue Verpackung | dieselben Gewichte, anders abgelegt | andere Medientypen, andere Zahl der Teile |
| andere Quantisierung | anderes Verfahren oder korrigiertes Runden | andere Größen der Gewichts-Blobs, anderer Eintrag zur Quantisierung |
| behobene Umwandlung | etwa Vokabular, Positionsangaben oder fehlende Tensoren | einzelne Blobs neu, meist die JSON-Dateien oder wenige Tensoren |
| nur Beiwerk | Vorlage, Parameter wie Temperatur oder Stoppzeichen, Lizenz | Gewichts-Blobs mit gleichem Digest, nur kleine Blobs neu |
| neue Gewichte | der Hersteller hat nachgebessert | alle Gewichts-Blobs neu bei gleicher Struktur |
Behobene Umwandlungen kommen bei neuen Modellen in den ersten Wochen häufig vor.
Bei Gemma 4 trafen auf dem Mac die ersten beiden Gründe zusammen: eine neue
Verpackung und eine neue Quantisierung. Für alle anderen Rechner hat sich an
den Gewichten nichts geändert. Das zeigt das Serverprotokoll vom 28.10.2026.
Die alte Fassung startete dort mit den Blobs a8bdd07a… für das Modell,
7e78b02d… für den Bildteil und 491f38af… für das Entwurfsmodell. Genau diese
drei Blobs nennt heute das GGUF-Manifest der Liste, mit "file_type": "Q4_K_M"
im Config-Blob. Neu ist also die Liste darüber und die zweite Variante darin.
eigene Darstellung nach der Registry und der Ablage am Gerät, Stand 09.11.2026
Gemma 4 liegt in zwei Verpackungen vor
GGUF bündelt Kopf und Gewichte in einer Datei
GGUF ist das Dateiformat von llama.cpp, einem Programm, um Sprachmodelle auf eigenen Rechnern auszuführen. Laut Spezifikation (externe Seite, github.com) ist es für Programme gedacht, die auf der Rechenbibliothek GGML aufbauen. Eine einzige Datei soll alles enthalten, was zum Laden eines Modells nötig ist. Sie ist so aufgebaut:
- die vier Zeichen
GGUF, eine Versionsnummer und die Zahl der Tensoren, - Metadaten als Paare aus Schlüssel und Wert, etwa Bauform, Vokabular, Gesprächsvorlage und Zahl der Schichten,
- je Tensor ein Eintrag mit Name, Form, Datentyp und Lage in der Datei,
- die Zahlen selbst, auf feste Grenzen ausgerichtet.
Die Ausrichtung erlaubt es, die Datei direkt in den Speicher abzubilden, statt sie zu kopieren.
Die Modelldatei der 26B-Variante lässt sich mit wenigen Zeilen Python nach der
Spezifikation auslesen. Sie hat 658 Tensoren und 56 Metadaten, darunter
general.architecture = gemma4, 30 Schichten, 128 Experten, von denen 8 je
Token rechnen, und general.file_type = 15. Die Zahl 15 steht für Q4_K_M. Neben
den 8 gewählten Experten nennt Googles
Modellkarte (externe Seite, ai.google.dev) einen geteilten Experten.
Ollamas safetensors legt jeden Tensor in einen eigenen Blob
safetensors ist das Format, in dem Hersteller wie Google ihre Gewichte bei Hugging Face veröffentlichen. Die Beschreibung (externe Seite, github.com) ist kurz: 8 Byte nennen die Länge eines Kopfes, dann folgt der Kopf als JSON, dann folgen die rohen Zahlen. Der Kopf sagt je Tensor, welchen Datentyp er hat, welche Form und an welcher Stelle seine Bytes stehen. Das Format kann keinen ausführbaren Code enthalten. Genau dafür wurde es entworfen.
Ein Hersteller verteilt seine Gewichte auf wenige große safetensors-Dateien. Ollama zerlegt sie für die MLX-Variante so, dass jeder Tensor ein eigener Blob ist. Einer der 1236 Blobs des 31B ist 65.028.524 Byte groß, sein Kopf 416 Byte:
$ head -c 8 sha256-… | xxd
00000000: a001 0000 0000 0000 ........
{
"__metadata__": { "quant_type": "nvfp4" },
"model.language_model.layers.0.mlp.down_proj.weight": {
"dtype": "U32", "shape": [5376, 2688], "data_offsets": [0, 57802752]
},
"model.language_model.layers.0.mlp.down_proj.weight.global_scale": {
"dtype": "F32", "shape": [], "data_offsets": [65028096, 65028100]
},
"model.language_model.layers.0.mlp.down_proj.weight.scale": {
"dtype": "U8", "shape": [5376, 1344], "data_offsets": [57802752, 65028096]
}
}
Die ersten acht Byte ergeben, von hinten gelesen, die Zahl 0x1a0, also 416.
Danach steht ein Tensor in drei Teilen:
- Die Gewichte liegen als
U32vor, als ganze Zahlen mit 32 Bit. Jede davon enthält acht Werte zu je 4 Bit, 2688 mal 8 ergibt 21.504 Werte je Zeile. - Die Blockskalen (
.scale) haben 8 Bit, eine je 16 Werte. 21.504 durch 16 ergibt 1344. - Die Tensorskala (
.global_scale) hat 32 Bit und gilt für den ganzen Tensor.
Das Feld quant_type nennt das Verfahren dahinter: NVFP4. Wie die drei Teile
zusammenwirken, erklärt der nächste Abschnitt.
eigene Darstellung nach der GGUF-Spezifikation, der safetensors-Beschreibung und einem Blob von gemma4:31b, Stand 09.11.2026
Beide nebeneinander
| GGUF | safetensors je Tensor (Ollama, MLX) | |
|---|---|---|
| Dateien je Modell | eine für das Sprachmodell, eigene für Bildteil und Entwurfsmodell | eine je Tensor, 1162 beim 26B |
| Kopf | binär, Schlüssel und Werte für das ganze Modell | JSON je Datei, Datentyp, Form, Lage |
| Vokabular und Vorlage | im Kopf der Datei | eigene JSON-Blobs des Herstellers |
| Quantisierung erkennbar an | general.file_type und dem Datentyp je Tensor | __metadata__.quant_type je Blob |
| gedacht für | llama.cpp und Programme auf GGML | Transformers, vLLM, MLX und andere |
| Deduplizierung | nur ganze Dateien | jeder Tensor einzeln |
Für Ollama hat die feine Zerlegung einen praktischen Vorteil. Ändert sich ein einzelner Tensor, muss nur dieser Blob neu heruntergeladen werden, und gleiche Tensoren zweier Modelle liegen nur einmal vor. Welche Engine welches Format liest, ordnet Nutzung und Anpassung von LLMs, Kapitel 05 über mehrere Programme hinweg ein.
Vier Bit je Gewicht reichen, wenn jeder Block eine eigene Skala hat
Die Gewichte von Gemma 4 veröffentlicht Google in BF16, also mit 16 Bit je Zahl. Das 31B mit 30,7 Milliarden Parametern wöge so rund 61 Gigabyte und ließe vom Arbeitsspeicher des Messgeräts mit 64 GB wenig übrig. Beide Varianten bei Ollama sind deshalb quantisiert: Jede Zahl wird gröber gespeichert, im Mittel mit etwas über 4 Bit. Das spart Platz und beim Antworten auch Zeit, wie der Abschnitt über das Tempo zeigt. Es kostet Genauigkeit, und die Kunst besteht darin, möglichst wenig davon zu verlieren.
Runden auf ein grobes Raster
Die einfachste Form geht in drei Schritten. Man sucht in einer Reihe von Zahlen den betragsgrößten Wert. Man teilt alle Zahlen durch eine Skala, sodass der größte Wert auf den Rand des Rasters fällt. Und man rundet jede Zahl auf die nächste Rasterstufe. Gespeichert werden die Stufen und die Skala. Beim Rechnen wird jede Stufe wieder mit der Skala malgenommen.
Ein Beispiel mit vier Zahlen und einem Raster aus ganzen Zahlen von −7 bis 7: Die Werte seien 0,021, −0,014, 0,003 und 0,035. Der größte Betrag ist 0,035, die Skala also 0,035 durch 7 gleich 0,005. Geteilt und gerundet ergeben sich 4, −3, 1 und 7. Zurückgerechnet sind das 0,020, −0,015, 0,005 und 0,035. Der größte Fehler liegt bei 0,002 und entsteht beim kleinen Wert 0,003: Er macht zwei Drittel dieses Werts aus. Beim größten Wert ist der Fehler null, bei den beiden anderen 0,001.
Das Problem steckt im größten Wert. Ein einzelner Ausreißer zieht die Skala hoch, und alle kleinen Zahlen landen auf wenigen Stufen nahe null. Deshalb bekommen kleine Blöcke von 16 bis 256 Zahlen je eine eigene Skala. Die Verfahren unterscheiden sich darin, wie groß ein Block ist, wie die Skala gespeichert wird und welches Raster die Werte haben.
Q4_0 teilt die Gewichte in Blöcke zu 32
Q4_0 gehört zu den Verfahren, die llama.cpp schon vor den k-quants von 2023 hatte, wie der Pull Request der k-quants (externe Seite, github.com) sie nennt. Im Quelltext von GGML (externe Seite, github.com) hat ein Block 32 Gewichte. Er speichert eine Skala in 16 Bit und 16 Byte für die Werte, je zwei Werte zu 4 Bit in einem Byte. Das sind 18 Byte für 32 Gewichte, also 4,5 Bit je Gewicht. Beim Zurückrechnen zieht GGML von jedem 4-Bit-Wert 8 ab und multipliziert mit der Skala, so steht es in der Funktion zum Zurückrechnen (externe Seite, raw.githubusercontent.com). Die Werte sind also ganze Zahlen von −8 bis 7, das Raster ist gleichmäßig.
Die k-quants fassen 256 Werte zu einem Superblock
2023 führte llama.cpp die sogenannten k-quants (externe Seite, github.com) ein. Sie fassen 256 Gewichte zu einem Superblock zusammen. Bei Q4_K besteht er aus acht Blöcken zu 32, und jeder Block hat eine eigene Skala und einen eigenen Mindestwert. Die Skalen selbst werden noch einmal mit 6 Bit quantisiert, relativ zu einer Skala des Superblocks. So kommt Q4_K auf 4,5 Bit je Gewicht, Q6_K mit Blöcken zu 16 auf 6,5625.
Q4_K_M bezeichnet eine Mischung dieser Typen. Der Name steht für das Rezept, nach dem llama.cpp die Tensoren eines Modells auf Typen verteilt. Laut Quelltext (externe Seite, github.com) bekommen zwei Arten von Tensoren in etwa der Hälfte der Schichten Q6_K: die Werte der Aufmerksamkeit und die Abwärtsprojektion. Die Ausgabematrix bekommt ebenfalls Q6_K, der Rest Q4_K. Wer den Datentyp jedes Tensors ausliest, sieht, wie verschieden dieses Rezept ausfallen kann:
| 31B GGUF | 26B GGUF | |
|---|---|---|
| Q4_K | 358 Tensoren, 14,25 GB | 28 Tensoren, 7,99 GB (Experten, erster Teil) |
| Q6_K | 53 Tensoren, 4,40 GB | keine |
| Q5_1 | keine | 29 Tensoren, 5,52 GB (Experten, Abwärtsprojektion) |
| Q5_K | keine | 2 Tensoren, 0,70 GB |
| Q8_0 | keine | 207 Tensoren, 2,80 GB (Aufmerksamkeit, geteilter Teil, Einbettung) |
| F32 | 422 kleine Tensoren | 392 kleine Tensoren |
Quelle: eigene Auslesung der GGUF-Köpfe nach der Spezifikation, 09.11.2026.
Beim 31B ist das das bekannte Bild. Beim 26B liegt unter derselben Bezeichnung weniger als die Hälfte der Bytes in Q4_K, der Rest in 5 bis 8 Bit. Der Grund liegt in der Bauform als Mixture of Experts. Bei 128 Experten machen sie fast alle Gewichte aus. Alles außerhalb der Experten ist klein und rechnet bei jedem Token mit, also kostet es wenig Platz, diesen Teil in 8 Bit zu speichern. Am Namen Q4_K_M lässt sich das nicht ablesen, das zeigt erst der Blick in die Datei.
Microscaling gibt jedem Block eine Zweierpotenz
Ein zweiter Weg kommt aus der Hardware-Industrie. Die Microscaling-Spezifikation (externe Seite, opencompute.org) der Open Compute Project Foundation von 2023 legt Formate fest, die Grafikchips direkt rechnen können. Mitgeschrieben haben unter anderem AMD, Arm, Intel, Microsoft, NVIDIA und Qualcomm. Für die Werte nehmen die Formate kleine Gleitkommazahlen:
- MXFP4 mit E2M1, also den Werten von 0 bis 6 aus dem Kasten oben,
- MXFP8 mit E4M3 oder E5M2.
Je 32 Werte teilen sich eine Skala im Format E8M0. Das ist ein reiner Exponent ohne Mantisse, die Skala ist also immer eine Zweierpotenz. MXFP4 kommt damit auf 4,25 Bit je Wert, MXFP8 auf 8,25.
Gleitkommawerte haben ein ungleichmäßiges Raster: dicht bei null, grob am Rand. Das passt zu Gewichten, denn die meisten liegen nahe null und nur wenige weit draußen.
eigene Darstellung nach dem GGML-Quelltext, der OCP-Microscaling-Spezifikation v1.0 und NVIDIAs Beschreibung von NVFP4
NVFP4 halbiert den Block und verfeinert die Skala
NVFP4 ist NVIDIAs Weiterentwicklung, eingeführt 2025 mit der Chipgeneration Blackwell. Laut NVIDIA (externe Seite, developer.nvidia.com) nutzt sie dieselben Werte E2M1 wie MXFP4, mit drei Unterschieden:
- Ein Block umfasst 16 Werte statt 32. Ein Ausreißer verdirbt also nur halb so viele Nachbarn.
- Die Skala jedes Blocks ist eine Zahl in E4M3 statt einer Zweierpotenz. Sie kann also auch 1,25 oder 0,875 sein und passt sich enger an den Block an.
- Weil E4M3 nur einen kleinen Wertebereich hat, kommt eine zweite Skala in 32 Bit für den ganzen Tensor dazu.
Das ergibt 4 Bit je Wert plus 8 Bit Skala je 16 Werte, also 4,5 Bit je Wert.
Genau diese drei Teile stehen im Blob von oben: die Werte als U32, die
Blockskalen als U8 und die Tensorskala als F32.
NVIDIAs Chips der Blackwell-Reihe rechnen NVFP4 in eigenen Rechenwerken. Auf Apples Grafikchips gehen die Rechenkerne von MLX (externe Seite, github.com) einen Umweg. Sie wandeln jeden 4-Bit-Wert per Bitverschiebung in eine Zahl mit 16 Bit um und multiplizieren erst dann. MLX kann in NVFP4 quantisieren und zurückrechnen seit Fassung 0.30.0, so steht es in den Release Notes (externe Seite, github.com). Die Doku (externe Seite, ml-explore.github.io) in Fassung 0.32.4 führt NVFP4 heute neben MXFP4, MXFP8 und dem älteren Verfahren mit ganzen Zahlen (affine). Für das Tempo zählt trotzdem vor allem, dass weniger Bytes aus dem Speicher gelesen werden.
Einen echten Block selbst quantisieren
Das folgende Modul nimmt zwei Blöcke zu je 32 echten Gewichten aus Gemma 4 31B. Es zeigt, was jedes der drei Verfahren daraus macht: welche Codes gespeichert werden, welche Werte beim Rechnen zurückkommen und wie groß der Fehler ist. Der zweite Block enthält einen Ausreißer. An ihm wird sichtbar, warum NVFP4 kleinere Blöcke nimmt.
Ein Block echter Gewichte in drei Verfahren
Q4_0, gewöhnlicher Block
- Skala
- −0,008545 (FP16)
- Bit je Wert
- 4,5
- Mittlerer Fehler
- 0,00211
- Größter Fehler
- 0,00415
Original zurück Fehler. Senkrecht bis ±0,07596, gleich für alle drei Verfahren dieses Blocks.
| Nr. | Original | Code | zurück | Fehler |
|---|---|---|---|---|
| Skala d = −0,008545 (FP16). Ein Wert ist Code mal d. | ||||
| 1 | −0,03809 | 4 | −0,03418 | 0,00391 |
| 2 | 0,00513 | −1 | 0,00854 | 0,00342 |
| 3 | 0,01031 | −1 | 0,00854 | 0,00177 |
| 4 | −0,00108 | 0 | 0,00000 | 0,00108 |
| 5 | 0,02246 | −3 | 0,02563 | 0,00317 |
| 6 | 0,01636 | −2 | 0,01709 | 0,00073 |
| 7 | 0,00885 | −1 | 0,00854 | 0,00031 |
| 8 | 0,00298 | 0 | 0,00000 | 0,00298 |
| 9 | 0,06128 | −7 | 0,05981 | 0,00146 |
| 10 | −0,00592 | 1 | −0,00854 | 0,00262 |
| 11 | −0,01117 | 1 | −0,00854 | 0,00262 |
| 12 | 0,01624 | −2 | 0,01709 | 0,00085 |
| 13 | −0,00604 | 1 | −0,00854 | 0,00250 |
| 14 | −0,01660 | 2 | −0,01709 | 0,00049 |
| 15 | 0,01978 | −2 | 0,01709 | 0,00269 |
| 16 | −0,00647 | 1 | −0,00854 | 0,00208 |
| 17 | 0,06836 | −8 | 0,06836 | 0,00000 |
| 18 | −0,00014 | 0 | 0,00000 | 0,00014 |
| 19 | 0,01733 | −2 | 0,01709 | 0,00024 |
| 20 | −0,00400 | 0 | 0,00000 | 0,00400 |
| 21 | −0,00308 | 0 | 0,00000 | 0,00308 |
| 22 | −0,03296 | 4 | −0,03418 | 0,00122 |
| 23 | −0,00097 | 0 | 0,00000 | 0,00097 |
| 24 | 0,01007 | −1 | 0,00854 | 0,00153 |
| 25 | 0,00314 | 0 | 0,00000 | 0,00314 |
| 26 | 0,00403 | 0 | 0,00000 | 0,00403 |
| 27 | 0,00008 | 0 | 0,00000 | 0,00008 |
| 28 | 0,01147 | −1 | 0,00854 | 0,00293 |
| 29 | 0,00220 | 0 | 0,00000 | 0,00220 |
| 30 | −0,00394 | 0 | 0,00000 | 0,00394 |
| 31 | −0,01294 | 2 | −0,01709 | 0,00415 |
| 32 | 0,01166 | −1 | 0,00854 | 0,00311 |
MXFP4, gewöhnlicher Block
- Skala
- 2−6 = 0,01563 (E8M0)
- Bit je Wert
- 4,25
- Mittlerer Fehler
- 0,00239
- Größter Fehler
- 0,00684
Original zurück Fehler. Senkrecht bis ±0,07596, gleich für alle drei Verfahren dieses Blocks.
| Nr. | Original | Code | zurück | Fehler |
|---|---|---|---|---|
| Skala 2−6 = 0,01563 (E8M0, Byte 121). Ein Wert ist E2M1 mal Skala. | ||||
| 1 | −0,03809 | 1 10 0 −2 | −0,03125 | 0,00684 |
| 2 | 0,00513 | 0 00 1 0,5 | 0,00781 | 0,00269 |
| 3 | 0,01031 | 0 00 1 0,5 | 0,00781 | 0,00250 |
| 4 | −0,00108 | 1 00 0 −0 | 0,00000 | 0,00108 |
| 5 | 0,02246 | 0 01 1 1,5 | 0,02344 | 0,00098 |
| 6 | 0,01636 | 0 01 0 1 | 0,01563 | 0,00073 |
| 7 | 0,00885 | 0 00 1 0,5 | 0,00781 | 0,00104 |
| 8 | 0,00298 | 0 00 0 0 | 0,00000 | 0,00298 |
| 9 | 0,06128 | 0 11 0 4 | 0,06250 | 0,00122 |
| 10 | −0,00592 | 1 00 1 −0,5 | −0,00781 | 0,00189 |
| 11 | −0,01117 | 1 00 1 −0,5 | −0,00781 | 0,00336 |
| 12 | 0,01624 | 0 01 0 1 | 0,01563 | 0,00061 |
| 13 | −0,00604 | 1 00 1 −0,5 | −0,00781 | 0,00177 |
| 14 | −0,01660 | 1 01 0 −1 | −0,01563 | 0,00098 |
| 15 | 0,01978 | 0 01 1 1,5 | 0,02344 | 0,00366 |
| 16 | −0,00647 | 1 00 1 −0,5 | −0,00781 | 0,00134 |
| 17 | 0,06836 | 0 11 0 4 | 0,06250 | 0,00586 |
| 18 | −0,00014 | 1 00 0 −0 | 0,00000 | 0,00014 |
| 19 | 0,01733 | 0 01 0 1 | 0,01563 | 0,00171 |
| 20 | −0,00400 | 1 00 1 −0,5 | −0,00781 | 0,00381 |
| 21 | −0,00308 | 1 00 0 −0 | 0,00000 | 0,00308 |
| 22 | −0,03296 | 1 10 0 −2 | −0,03125 | 0,00171 |
| 23 | −0,00097 | 1 00 0 −0 | 0,00000 | 0,00097 |
| 24 | 0,01007 | 0 00 1 0,5 | 0,00781 | 0,00226 |
| 25 | 0,00314 | 0 00 0 0 | 0,00000 | 0,00314 |
| 26 | 0,00403 | 0 00 1 0,5 | 0,00781 | 0,00378 |
| 27 | 0,00008 | 0 00 0 0 | 0,00000 | 0,00008 |
| 28 | 0,01147 | 0 00 1 0,5 | 0,00781 | 0,00366 |
| 29 | 0,00220 | 0 00 0 0 | 0,00000 | 0,00220 |
| 30 | −0,00394 | 1 00 1 −0,5 | −0,00781 | 0,00388 |
| 31 | −0,01294 | 1 01 0 −1 | −0,01563 | 0,00269 |
| 32 | 0,01166 | 0 00 1 0,5 | 0,00781 | 0,00385 |
NVFP4, gewöhnlicher Block
- Skalen
- 128 und 144 (E4M3) mal 0,00007993 (FP32)
- Bit je Wert
- 4,5
- Mittlerer Fehler
- 0,00115
- Größter Fehler
- 0,00284
Original zurück Fehler. Senkrecht bis ±0,07596, gleich für alle drei Verfahren dieses Blocks.
| Nr. | Original | Code | zurück | Fehler |
|---|---|---|---|---|
| Werte 1 bis 16: Skala 128 (E4M3) mal 0,00007993 (FP32) = 0,01023. Ein Wert ist E2M1 mal beide Skalen. | ||||
| 1 | −0,03809 | 1 11 0 −4 | −0,04092 | 0,00284 |
| 2 | 0,00513 | 0 00 1 0,5 | 0,00512 | 0,00001 |
| 3 | 0,01031 | 0 01 0 1 | 0,01023 | 0,00008 |
| 4 | −0,00108 | 1 00 0 −0 | 0,00000 | 0,00108 |
| 5 | 0,02246 | 0 10 0 2 | 0,02046 | 0,00200 |
| 6 | 0,01636 | 0 01 1 1,5 | 0,01535 | 0,00101 |
| 7 | 0,00885 | 0 01 0 1 | 0,01023 | 0,00138 |
| 8 | 0,00298 | 0 00 1 0,5 | 0,00512 | 0,00214 |
| 9 | 0,06128 | 0 11 1 6 | 0,06138 | 0,00010 |
| 10 | −0,00592 | 1 00 1 −0,5 | −0,00512 | 0,00081 |
| 11 | −0,01117 | 1 01 0 −1 | −0,01023 | 0,00094 |
| 12 | 0,01624 | 0 01 1 1,5 | 0,01535 | 0,00089 |
| 13 | −0,00604 | 1 00 1 −0,5 | −0,00512 | 0,00093 |
| 14 | −0,01660 | 1 01 1 −1,5 | −0,01535 | 0,00126 |
| 15 | 0,01978 | 0 10 0 2 | 0,02046 | 0,00069 |
| 16 | −0,00647 | 1 00 1 −0,5 | −0,00512 | 0,00135 |
| Werte 17 bis 32: Skala 144 (E4M3) mal 0,00007993 (FP32) = 0,01151. Ein Wert ist E2M1 mal beide Skalen. | ||||
| 17 | 0,06836 | 0 11 1 6 | 0,06906 | 0,00070 |
| 18 | −0,00014 | 1 00 0 −0 | 0,00000 | 0,00014 |
| 19 | 0,01733 | 0 01 1 1,5 | 0,01726 | 0,00007 |
| 20 | −0,00400 | 1 00 1 −0,5 | −0,00575 | 0,00176 |
| 21 | −0,00308 | 1 00 1 −0,5 | −0,00575 | 0,00267 |
| 22 | −0,03296 | 1 10 1 −3 | −0,03453 | 0,00157 |
| 23 | −0,00097 | 1 00 0 −0 | 0,00000 | 0,00097 |
| 24 | 0,01007 | 0 01 0 1 | 0,01151 | 0,00144 |
| 25 | 0,00314 | 0 00 1 0,5 | 0,00575 | 0,00261 |
| 26 | 0,00403 | 0 00 1 0,5 | 0,00575 | 0,00173 |
| 27 | 0,00008 | 0 00 0 0 | 0,00000 | 0,00008 |
| 28 | 0,01147 | 0 01 0 1 | 0,01151 | 0,00003 |
| 29 | 0,00220 | 0 00 0 0 | 0,00000 | 0,00220 |
| 30 | −0,00394 | 1 00 1 −0,5 | −0,00575 | 0,00182 |
| 31 | −0,01294 | 1 01 0 −1 | −0,01151 | 0,00143 |
| 32 | 0,01166 | 0 01 0 1 | 0,01151 | 0,00015 |
Q4_0, Block mit Ausreißer
- Skala
- −0,01587 (FP16)
- Bit je Wert
- 4,5
- Mittlerer Fehler
- 0,00414
- Größter Fehler
- 0,00793
Original zurück Fehler. Senkrecht bis ±0,13965, gleich für alle drei Verfahren dieses Blocks.
| Nr. | Original | Code | zurück | Fehler |
|---|---|---|---|---|
| Skala d = −0,01587 (FP16). Ein Wert ist Code mal d. | ||||
| 1 | −0,01941 | 1 | −0,01587 | 0,00354 |
| 2 | 0,00696 | 0 | 0,00000 | 0,00696 |
| 3 | −0,02539 | 2 | −0,03174 | 0,00635 |
| 4 | −0,02209 | 1 | −0,01587 | 0,00623 |
| 5 | −0,02515 | 2 | −0,03174 | 0,00659 |
| 6 | 0,12695 | −8 | 0,12695 | 0,00000 |
| 7 | 0,00632 | 0 | 0,00000 | 0,00632 |
| 8 | 0,01672 | −1 | 0,01587 | 0,00085 |
| 9 | −0,01038 | 1 | −0,01587 | 0,00549 |
| 10 | −0,00147 | 0 | 0,00000 | 0,00147 |
| 11 | −0,02466 | 2 | −0,03174 | 0,00708 |
| 12 | 0,01080 | −1 | 0,01587 | 0,00507 |
| 13 | −0,02124 | 1 | −0,01587 | 0,00537 |
| 14 | −0,01093 | 1 | −0,01587 | 0,00494 |
| 15 | −0,00011 | 0 | 0,00000 | 0,00011 |
| 16 | −0,00500 | 0 | 0,00000 | 0,00500 |
| 17 | −0,01373 | 1 | −0,01587 | 0,00214 |
| 18 | −0,00409 | 0 | 0,00000 | 0,00409 |
| 19 | −0,01575 | 1 | −0,01587 | 0,00012 |
| 20 | 0,00793 | 0 | 0,00000 | 0,00793 |
| 21 | −0,00595 | 0 | 0,00000 | 0,00595 |
| 22 | 0,00629 | 0 | 0,00000 | 0,00629 |
| 23 | 0,00247 | 0 | 0,00000 | 0,00247 |
| 24 | 0,00150 | 0 | 0,00000 | 0,00150 |
| 25 | −0,00739 | 0 | 0,00000 | 0,00739 |
| 26 | 0,00105 | 0 | 0,00000 | 0,00105 |
| 27 | 0,00861 | −1 | 0,01587 | 0,00726 |
| 28 | −0,00540 | 0 | 0,00000 | 0,00540 |
| 29 | 0,00080 | 0 | 0,00000 | 0,00080 |
| 30 | 0,00124 | 0 | 0,00000 | 0,00124 |
| 31 | −0,01892 | 1 | −0,01587 | 0,00305 |
| 32 | 0,01129 | −1 | 0,01587 | 0,00458 |
MXFP4, Block mit Ausreißer
- Skala
- 2−5 = 0,03125 (E8M0)
- Bit je Wert
- 4,25
- Mittlerer Fehler
- 0,00414
- Größter Fehler
- 0,00769
Original zurück Fehler. Senkrecht bis ±0,13965, gleich für alle drei Verfahren dieses Blocks.
| Nr. | Original | Code | zurück | Fehler |
|---|---|---|---|---|
| Skala 2−5 = 0,03125 (E8M0, Byte 122). Ein Wert ist E2M1 mal Skala. | ||||
| 1 | −0,01941 | 1 00 1 −0,5 | −0,01563 | 0,00378 |
| 2 | 0,00696 | 0 00 0 0 | 0,00000 | 0,00696 |
| 3 | −0,02539 | 1 01 0 −1 | −0,03125 | 0,00586 |
| 4 | −0,02209 | 1 00 1 −0,5 | −0,01563 | 0,00647 |
| 5 | −0,02515 | 1 01 0 −1 | −0,03125 | 0,00610 |
| 6 | 0,12695 | 0 11 0 4 | 0,12500 | 0,00195 |
| 7 | 0,00632 | 0 00 0 0 | 0,00000 | 0,00632 |
| 8 | 0,01672 | 0 00 1 0,5 | 0,01563 | 0,00110 |
| 9 | −0,01038 | 1 00 1 −0,5 | −0,01563 | 0,00525 |
| 10 | −0,00147 | 1 00 0 −0 | 0,00000 | 0,00147 |
| 11 | −0,02466 | 1 01 0 −1 | −0,03125 | 0,00659 |
| 12 | 0,01080 | 0 00 1 0,5 | 0,01563 | 0,00482 |
| 13 | −0,02124 | 1 00 1 −0,5 | −0,01563 | 0,00562 |
| 14 | −0,01093 | 1 00 1 −0,5 | −0,01563 | 0,00470 |
| 15 | −0,00011 | 1 00 0 −0 | 0,00000 | 0,00011 |
| 16 | −0,00500 | 1 00 0 −0 | 0,00000 | 0,00500 |
| 17 | −0,01373 | 1 00 1 −0,5 | −0,01563 | 0,00189 |
| 18 | −0,00409 | 1 00 0 −0 | 0,00000 | 0,00409 |
| 19 | −0,01575 | 1 00 1 −0,5 | −0,01563 | 0,00012 |
| 20 | 0,00793 | 0 00 1 0,5 | 0,01563 | 0,00769 |
| 21 | −0,00595 | 1 00 0 −0 | 0,00000 | 0,00595 |
| 22 | 0,00629 | 0 00 0 0 | 0,00000 | 0,00629 |
| 23 | 0,00247 | 0 00 0 0 | 0,00000 | 0,00247 |
| 24 | 0,00150 | 0 00 0 0 | 0,00000 | 0,00150 |
| 25 | −0,00739 | 1 00 0 −0 | 0,00000 | 0,00739 |
| 26 | 0,00105 | 0 00 0 0 | 0,00000 | 0,00105 |
| 27 | 0,00861 | 0 00 1 0,5 | 0,01563 | 0,00702 |
| 28 | −0,00540 | 1 00 0 −0 | 0,00000 | 0,00540 |
| 29 | 0,00080 | 0 00 0 0 | 0,00000 | 0,00080 |
| 30 | 0,00124 | 0 00 0 0 | 0,00000 | 0,00124 |
| 31 | −0,01892 | 1 00 1 −0,5 | −0,01563 | 0,00330 |
| 32 | 0,01129 | 0 00 1 0,5 | 0,01563 | 0,00433 |
NVFP4, Block mit Ausreißer
- Skalen
- 256 und 40 (E4M3) mal 0,00007993 (FP32)
- Bit je Wert
- 4,5
- Mittlerer Fehler
- 0,00169
- Größter Fehler
- 0,00500
Original zurück Fehler. Senkrecht bis ±0,13965, gleich für alle drei Verfahren dieses Blocks.
| Nr. | Original | Code | zurück | Fehler |
|---|---|---|---|---|
| Werte 1 bis 16: Skala 256 (E4M3) mal 0,00007993 (FP32) = 0,02046. Ein Wert ist E2M1 mal beide Skalen. | ||||
| 1 | −0,01941 | 1 01 0 −1 | −0,02046 | 0,00105 |
| 2 | 0,00696 | 0 00 1 0,5 | 0,01023 | 0,00327 |
| 3 | −0,02539 | 1 01 0 −1 | −0,02046 | 0,00493 |
| 4 | −0,02209 | 1 01 0 −1 | −0,02046 | 0,00163 |
| 5 | −0,02515 | 1 01 0 −1 | −0,02046 | 0,00469 |
| 6 | 0,12695 | 0 11 1 6 | 0,12277 | 0,00419 |
| 7 | 0,00632 | 0 00 1 0,5 | 0,01023 | 0,00391 |
| 8 | 0,01672 | 0 01 0 1 | 0,02046 | 0,00374 |
| 9 | −0,01038 | 1 00 1 −0,5 | −0,01023 | 0,00015 |
| 10 | −0,00147 | 1 00 0 −0 | 0,00000 | 0,00147 |
| 11 | −0,02466 | 1 01 0 −1 | −0,02046 | 0,00420 |
| 12 | 0,01080 | 0 00 1 0,5 | 0,01023 | 0,00057 |
| 13 | −0,02124 | 1 01 0 −1 | −0,02046 | 0,00078 |
| 14 | −0,01093 | 1 00 1 −0,5 | −0,01023 | 0,00069 |
| 15 | −0,00011 | 1 00 0 −0 | 0,00000 | 0,00011 |
| 16 | −0,00500 | 1 00 0 −0 | 0,00000 | 0,00500 |
| Werte 17 bis 32: Skala 40 (E4M3) mal 0,00007993 (FP32) = 0,003197. Ein Wert ist E2M1 mal beide Skalen. | ||||
| 17 | −0,01373 | 1 11 0 −4 | −0,01279 | 0,00094 |
| 18 | −0,00409 | 1 01 1 −1,5 | −0,00480 | 0,00071 |
| 19 | −0,01575 | 1 11 0 −4 | −0,01279 | 0,00296 |
| 20 | 0,00793 | 0 10 0 2 | 0,00639 | 0,00154 |
| 21 | −0,00595 | 1 10 0 −2 | −0,00639 | 0,00044 |
| 22 | 0,00629 | 0 10 0 2 | 0,00639 | 0,00011 |
| 23 | 0,00247 | 0 01 0 1 | 0,00320 | 0,00073 |
| 24 | 0,00150 | 0 00 1 0,5 | 0,00160 | 0,00010 |
| 25 | −0,00739 | 1 10 0 −2 | −0,00639 | 0,00099 |
| 26 | 0,00105 | 0 00 1 0,5 | 0,00160 | 0,00055 |
| 27 | 0,00861 | 0 10 1 3 | 0,00959 | 0,00099 |
| 28 | −0,00540 | 1 01 1 −1,5 | −0,00480 | 0,00061 |
| 29 | 0,00080 | 0 00 1 0,5 | 0,00160 | 0,00080 |
| 30 | 0,00124 | 0 00 1 0,5 | 0,00160 | 0,00036 |
| 31 | −0,01892 | 1 11 1 −6 | −0,01918 | 0,00026 |
| 32 | 0,01129 | 0 11 0 4 | 0,01279 | 0,00150 |
| Verfahren und Block | Bit je Wert | mittlerer Fehler | größter Fehler |
|---|---|---|---|
| Q4_0, gewöhnlich | 4,5 | 0,00211 | 0,00415 |
| MXFP4, gewöhnlich | 4,25 | 0,00239 | 0,00684 |
| NVFP4, gewöhnlich | 4,5 | 0,00115 | 0,00284 |
| Q4_0, mit Ausreißer | 4,5 | 0,00414 | 0,00793 |
| MXFP4, mit Ausreißer | 4,25 | 0,00414 | 0,00769 |
| NVFP4, mit Ausreißer | 4,5 | 0,00169 | 0,00500 |
Im gewöhnlichen Block liegt der mittlere Fehler bei NVFP4 bei 0,00115. Q4_0 kommt auf 0,00211, MXFP4 auf 0,00239. Im Block mit dem Ausreißer wachsen alle drei, NVFP4 bleibt mit 0,00169 am kleinsten. Dafür sorgen die beiden Skalen dieses Blocks: Die Hälfte mit dem Ausreißer bekommt eine grobe, die andere eine feine.
Die Codes für NVFP4 stammen aus Ollamas Datei auf dem Messgerät. Rechnet man denselben Block nach NVIDIAs Vorschrift selbst, kommen bitgenau dieselben Codes und Skalen heraus. Die Werte für Q4_0 und MXFP4 sind nach den Vorschriften von GGML und der Microscaling-Spezifikation nachgerechnet.
Was in Gemma 4 steckt
Die MLX-Varianten sind nicht einheitlich quantisiert. Der Kopf jedes Blobs nennt das Verfahren, und ausgezählt ergibt sich:
| 26B MLX | 31B MLX | |
|---|---|---|
| NVFP4 | 245 Tensoren, 13,84 GB, darunter alle Experten | 411 Tensoren, 17,27 GB |
| MXFP8 | 44 Tensoren, 1,08 GB: Einbettung, Aufmerksamkeit in 9 von 30 Schichten, Abwärtsprojektion in 14 von 30, zwei Tensoren des Entwurfsmodells | keine |
| BF16 | 772 Tensoren, 1,17 GB, vor allem Normen und Bildteil | 825 Tensoren, 2,09 GB |
| F32 | 101 kleine Tensoren mit Skalen | keine |
Quelle: eigene Auszählung der Blob-Köpfe, 09.11.2026.
Beim 26B folgt die MLX-Variante damit derselben Idee wie Q4_K_M. Einige
Tensoren bekommen mehr Bit, die Masse der Experten bekommt 4 Bit. Die Datei
hf_quant_config.json im Paket nennt als Werkzeug NVIDIAs Model Optimizer in
einer Vorabfassung 0.47 und als Verfahren MIXED_PRECISION. Wer genau die
Datei erzeugt hat, sagt das Paket nicht. Die NVFP4-Fassungen, die NVIDIA selbst
bei Hugging Face anbietet, nennen andere Werkzeugfassungen und andere
Einstellungen.
Die MLX-Variante antwortet schneller, der Wächter hat vor allem das Laden gemessen
Weniger Bytes je Token heißt also schnellere Antworten. Das MacBook Pro mit M4 Max hat laut Apple (externe Seite, support.apple.com) eine Speicherbandbreite von 546 GB/s. Beim dichten 31B liest jedes Token das ganze Sprachmodell, ohne Bildteil und Entwurfsmodell. In der MLX-Variante sind das 17,27 GB, in der GGUF-Variante 18,67 GB. Daraus folgen als Obergrenze 31,6 und 29,2 Token je Sekunde. Die Bytes allein erklären also höchstens einen Unterschied von acht Prozent.
Die Messung
Gemessen habe ich beide Varianten beider Modelle im selben Ollama, im Wechsel.
Es gab drei Aufgaben: eine Erklärung, ein Stück Programmcode, einen kurzen
Brief. Jede Antwort hatte bis zu 400 Token, bei Temperatur 0 und ohne
Denkspur. Das Feld runner der
Programmschnittstelle (externe Seite, raw.githubusercontent.com) wählt die
Variante. Ollama gibt für jeden Aufruf getrennt an, wie lange das Laden, das
Einlesen und das Antworten gedauert haben. Neben der Messung liefen andere
Programme. Die Systemlast (Load Average) lag bei diesem Vergleich zwischen 4,4
und 10,3.
| 26B MLX | 26B GGUF | 31B MLX | 31B GGUF | |
|---|---|---|---|---|
| Antworten, Token je Sekunde | 115,8 | 90,6 | 30,6 | 25,3 |
| Spanne | 103,6 bis 140,2 | 62,8 bis 98,6 | 26,9 bis 44,5 | 21,7 bis 28,4 |
| Einlesen von gut 2600 Token, Token je Sekunde | 1598 | 1472 | 158 | 152 |
Mediane aus 12 Läufen beim Antworten und 4 beim Einlesen. Eigene Messung, 09.11.2026, Ollama 0.40.15.
Aus den Medianen ohne Rundung folgt: Die MLX-Variante antwortet beim 26B um 28 Prozent schneller (115,8 gegen 90,6), beim 31B um 21 Prozent (30,6 gegen 25,3). Beim Einlesen liegt sie mit 9 und 4 Prozent nur knapp vorn. Zwischen den Läufen lagen Höchst- und Tiefstwert bis zu 57 Prozent des Medians auseinander (31B in MLX). Für sich genommen ist deshalb jeder einzelne Lauf wenig wert.
Das Entwurfsmodell hilft, beim 26B vor allem der GGUF-Variante
Beide Varianten bringen ein kleines Entwurfsmodell mit, bei Google „Gemma 4 MTP“ genannt. Google hat diese Entwurfsmodelle am 16.04.2026 veröffentlicht (externe Seite, ai.google.dev), gut zwei Wochen nach den Modellen selbst. Es nutzt ein Verfahren namens Speculative Decoding: Das kleine Modell schlägt mehrere Token vor, und das große prüft sie in einem einzigen Lesedurchgang. Stimmen die Vorschläge, liefert ein Lesen mehrere Token. Am Ergebnis ändert das nichts, weil das große Modell jeden Vorschlag bestätigt oder verwirft. Ollama schaltet das Verfahren seit Fassung 0.31.1 auf dem Mac selbst ein. Wie viele Token es vorschlagen lässt, stellt es nach den Release Notes (externe Seite, github.com) ebenfalls selbst ein.
Abschalten lässt es sich für eine Messung auf zwei Wegen. In der MLX-Variante
fällt es weg, sobald die Anfrage Wahrscheinlichkeiten je Token anfordert, so
steht es im Quelltext (externe Seite, raw.githubusercontent.com). In der
GGUF-Variante setzt der Parameter draft_num_predict auf 0 die Zahl der
Vorschläge auf null. Damit lassen sich Engine und Entwurfsmodell getrennt
messen:
| Token je Sekunde | 26B MLX | 26B GGUF | 31B MLX | 31B GGUF |
|---|---|---|---|---|
| mit Entwurfsmodell | 102,8 | 81,7 | 31,1 | 23,7 |
| ohne Entwurfsmodell | 98,5 | 41,4 | 18,7 | 12,8 |
| Faktor durch das Entwurfsmodell | 1,04 | 1,97 | 1,67 | 1,86 |
Mediane aus 6 Läufen je Zelle, eigene Messung, 09.11.2026. Die Läufe des 31B liefen unter deutlich höherer Systemlast als alle anderen, zwischen 15,5 und 42,5. Ihre Werte sind deshalb unsicherer als die des 26B.
Aus der Tabelle folgt:
- Beim 31B, dem dichten Modell, steigert das Entwurfsmodell das Tempo in beiden Varianten um mehr als die Hälfte. Der Faktor beträgt 1,7 bei MLX und 1,9 bei GGUF. Mit ihm liegt die MLX-Variante bei 31,1 Token je Sekunde und damit knapp unter der Obergrenze von 31,6, die ohne Entwurf gilt. Ohne Entwurf erreicht MLX 59 Prozent davon (18,7 von 31,6), die GGUF-Variante 44 Prozent (12,8 von 29,2).
- Beim 26B, dem Modell aus Experten, bringt das Entwurfsmodell der MLX-Variante fast nichts. Google erklärt das in der Doku zu MTP (externe Seite, ai.google.dev). Beim 26B A4B kann jedes Token andere Experten wählen, also holt das Prüfen der Vorschläge zusätzliche Gewichte aus dem Speicher. Bei einer Anfrage zur Zeit bringe der Entwurf auf Geräten ohne gute Parallelität womöglich keinen Gewinn. Die Messung zeigt genau das für MLX.
- Ohne Entwurfsmodell rechnet MLX das 26B 2,4-mal so schnell wie llama.cpp. Je Token liest die MLX-Variante grob 2,7 GB. Die GGUF-Variante liest wegen ihrer 8-Bit-Anteile grob 3,4 GB. Das erklärt einen Faktor von 1,3, den Rest liefert die Engine selbst. MLX nutzt hier knapp die Hälfte der Bandbreite, llama.cpp in Ollama ein Viertel. Beide Anteile sind eine grobe Rechnung aus Dateigrößen und Expertenzahl.
Am 30.05.2026 fand eine Messung auf demselben Gerät das Gegenteil. Ein Modell lief dort über MLX langsamer als über llama.cpp, nachzulesen in Elf Wege, ein lokales Modell schneller zu machen. Gemessen war damals ein anderes Modell mit anderen Programmen. Ollama hat seine Anbindung an MLX seither in vielen Fassungen überarbeitet. Ein Vergleich zweier Engines gilt deshalb für Fassung, Modell und Gerät, an denen er gemessen ist.
eigene Darstellung; Bandbreite laut Apple, Bytes je Token und Tempo aus eigener Messung am 09.11.2026
Das Laden erklärt die Zeiten des Wächters
Die Funktionsprobe des Wächters misst etwas anderes als Token je Sekunde. Sie schickt eine Aufgabe über eine Zwischenschicht an Ollama und stoppt die Zeit bis zur fertigen Antwort, einmal je Modell. In dieser Zeit steckt auch das Laden, falls das Modell gerade nicht im Speicher liegt. Und das Laden unterscheidet die Varianten am deutlichsten:
| Laden nach dem Entladen | MLX | GGUF |
|---|---|---|
| 26B | 2,0 bis 6,3 s | 2,4 bis 12,2 s, dazu 2,2 s beim ersten Aufruf |
| 31B | 4,0 bis 7,5 s | 9,4 bis 11,0 s, dazu 12,0 bis 13,5 s beim ersten Aufruf |
Eigene Messung, je 4 Läufe, 09.11.2026. Die Zeiten hängen davon ab, ob das Betriebssystem die Dateien noch im Speicher hält.
Beim 31B dauert das Laden der GGUF-Variante 2 bis 7 Sekunden länger als das der MLX-Variante. Rechnet man den ersten Aufruf dazu, bei dem die GGUF-Variante weitere 12,0 bis 13,5 Sekunden braucht, sind es 13,9 bis 20,5 Sekunden. Der Wächter maß 24,1 gegen 10,6 Sekunden, ein Unterschied von 13,5. Das liegt knapp unter dieser Spanne und passt zur Annahme, dass er beide Male ein ungeladenes Modell traf. Protokolliert ist das nicht.
Woran die Zahlen hängen
Die Ergebnisse waren in beiden Varianten inhaltlich gleichwertig, bei der Funktionsprobe des Wächters wie in den eigenen Läufen. Das spricht für einen schnelleren Ausführungsweg bei gleichem Modell. Wortgleich sind die Antworten trotzdem selten: Die Gewichte sind verschieden gerundet, und die Zahl der Antworttoken wich je Aufgabe um einige Prozent ab. Ob die eine Variante besser antwortet als die andere, hat diese Messung nicht untersucht. Sie lief an einem Tag, auf einem Gerät, mit wenigen Läufen je Zelle und neben anderer Last. Wer die Zahlen übernehmen will, misst auf dem eigenen Gerät nach.
So sehen Sie selbst nach
Alles, was dieser Beitrag beschreibt, lässt sich auf dem eigenen Rechner mit Bordmitteln prüfen. Den Steckbrief eines Modells zeigt Ollama selbst:
$ ollama show gemma4:26b
Model
architecture gemma4
parameters 26.2B
quantization nvfp4
requires 0.34.1
renderer gemma4-large
parser gemma4
runner mlx
available runners mlx:sha256:48eb98ec778c,
llamacpp:sha256:001e5dafc3c7
Die Ausgabe ist gekürzt. Die Zeile available runners nennt beide Varianten
mit dem Anfang ihres Digests. Das Manifest und seine Teile lassen sich direkt
lesen:
# which list does the name point to?
readlink ~/.ollama/models/manifests-v2/ollama.com/library/gemma4/26b
# how many parts, of which kind?
cd ~/.ollama/models/blobs
jq -r '.layers[].mediaType' sha256-48eb98ec… | sort | uniq -c
# does the file match its name?
shasum -a 256 sha256-ed3c4359…
Die andere Variante holt ein versteckter Schalter dazu, der in der Hilfe nicht
erscheint und im Quelltext (externe Seite, raw.githubusercontent.com)
steht: ollama pull gemma4:26b --runner llamacpp. Danach liegen beide
Varianten nebeneinander, und der Name zeigt auf einem Mac weiter auf MLX. Das
kostet hier 18,7 GB zusätzlich.
So hat es auch der Wächter gemacht, der diesen Beitrag ausgelöst hat. Er kopiert jedes Modell vor dem Neuladen und löscht die Kopie nach einer Woche, wenn das neue sich bewährt hat. Was sich zwischen beiden Fassungen geändert hat, hält er seit diesem Fall vor dem Löschen fest: Format, Quantisierung, Runner und Größe.
Quellen
33 Einträge, davon 1 Schlüsselarbeit30 erreichbar · 3 noch nicht geprüft
Erreichbarkeit automatisch geprüft
SchlüsselarbeitDokumentationerreichbar
Ollama, Modelfile reference (externe Seite, docs.ollama.com)
docs.ollama.comgeprüft 10.11.2026
Die Parameterliste des Programms, das ein Modell auf dem eigenen Rechner ausführt. Sie beantwortet die Frage, wem die Regler gehören: Sie stehen in der Datei, mit der die Ausführung eingerichtet wird. Im Modell stehen sie nicht. Von den elf Einträgen der Tabelle wirken sieben auf die Auswahl des nächsten Token, dazu einer auf das Tempo und drei auf Umfang und Abbruch. Zu Min-P steht dort „Alternative to the top_p“, es ersetzt also einen Schnitt. Der Unterstrich geht beim Abruf verloren, weil die Seite ihn als Auszeichnung liest; deshalb ist diese Stelle ohne hinterlegtes Zitat.
Datenerreichbar
Gemma 4 bei Ollama, Manifest-Liste von gemma4:26b (externe Seite, registry.ollama.ai)
registry.ollama.aigeprüft 10.11.2026
Die Manifest-Liste, die Ollamas Registry für gemma4:26b ausliefert, abgerufen am 09.11.2026. Sie nennt zwei Varianten: eine GGUF-Datei für llama.cpp mit 18,73 GB und Tensoren in safetensors für MLX mit 16,15 GB. Bei gemma4:31b sind es 20,39 und 19,42 GB.
Eigene Messungerreichbar
Gemma 4 bei Ollama, eigene Tempomessung beider Varianten (externe Seite, ki.herwig.de)
ki.herwig.degeprüft 10.11.2026
Eigene Messung beider Varianten von gemma4:26b und gemma4:31b mit Ollama 0.40.15 auf einem MacBook Pro M4 Max am 09.11.2026. Beim Antworten lag MLX vor llama.cpp, beim 26B mit 115,8 gegen 90,6 Token je Sekunde im Median. Ohne Entwurfsmodell sank das Tempo bei beiden Laufzeiten, bei llama.cpp auf etwa die Hälfte.
Dokumentationerreichbar
Ollama 0.40.15, Quelltext der Manifestablage (externe Seite, raw.githubusercontent.com)
raw.githubusercontent.comgeprüft 10.11.2026
Der Quelltext, mit dem Ollama 0.40.15 Manifeste ablegt, auswählt, prüft und löscht. Ein Modellname zeigt auf eine Manifest-Liste mit je einem Kindmanifest für llama.cpp und für MLX. Ein Mac mit Apple Silicon wählt zuerst MLX, alle anderen Rechner wählen zuerst llama.cpp. Für ältere Fassungen schreibt Ollama einen Rückfall-Anker, an den die Manifest-Blobs als Layer angehängt sind. Die Adresse zeigt auf einen festen Stand.
Dokumentationerreichbar
Ollama 0.40.15, Quelltext der Blob-Ablage (externe Seite, raw.githubusercontent.com)
raw.githubusercontent.comgeprüft 10.11.2026
Der Quelltext, mit dem Ollama 0.40.15 den Ablageort eines Blobs bildet. Der Dateiname ist der Digest, dessen Doppelpunkt nach sha256 dabei zum Bindestrich wird, und alle Blobs liegen im Verzeichnis blobs. Gleiche Bytes ergeben denselben Namen und liegen deshalb nur einmal auf der Platte. Die Adresse zeigt auf einen festen Stand.
Dokumentationerreichbar
raw.githubusercontent.comgeprüft 10.11.2026
Der Quelltext, mit dem die MLX-Laufzeit von Ollama 0.40.15 ein mitgeliefertes Entwurfsmodell für spekulatives Dekodieren einsetzt. Bringt das Modell einen Entwurfskopf mit, entwirft jede Anfrage Token voraus, außer sie verlangt Logprobs. Dazu gehört die Tabelle der Quantisierungsarten derselben Laufzeit mit ihren Gruppengrößen. Die Adresse zeigt auf einen festen Stand.
Dokumentationerreichbar
raw.githubusercontent.comgeprüft 10.11.2026
Der Quelltext, mit dem Ollama 0.40.15 festlegt, wer den Prompt eines Modells baut, ein Modell herunterlädt und kopiert. Nennt die Konfiguration einen Renderer und einen Parser, baut Go-Code den Prompt und zerlegt die Antwort. Vor dem Herunterladen der Modellteile vergleicht Ollama das Feld requires mit der eigenen Fassung und bricht bei einer älteren ab. Nach dem Herunterladen rechnet es die Prüfsumme jedes neuen Blobs nach und löscht eine Datei, deren Summe nicht stimmt. Die Adresse zeigt auf einen festen Stand.
Dokumentationerreichbar
raw.githubusercontent.comgeprüft 10.11.2026
Der Quelltext der Kommandozeile von Ollama 0.40.15. Die Befehle pull und run kennen einen versteckten Schalter --runner, mit dem man aus einer Manifest-Liste eine bestimmte Variante wählt (mlx, ggml oder llamacpp). Die Hilfe von Ollama führt ihn nicht auf. Die Adresse zeigt auf einen festen Stand.
Dokumentationnoch nicht geprüft
raw.githubusercontent.com
Der Quelltext, mit dem Ollama 0.40.15 die Blobs eines Modells mit einzelnen Tensoren herunterlädt. Es rechnet die SHA-256-Prüfsumme während des Schreibens mit und entfernt die Zwischendatei, wenn sie nicht zum Digest passt. Ein Blob, der in passender Größe schon vorliegt, wird übersprungen. Die Adresse zeigt auf einen festen Stand.
Dokumentationnoch nicht geprüft
raw.githubusercontent.com
Der Quelltext, in dem Ollama 0.40.15 die Anfragen seiner Programmschnittstelle festlegt. Generate-, Chat- und Pull-Anfrage haben ein Feld runner, das aus einer Manifest-Liste eine Variante wählt. Die Adresse zeigt auf einen festen Stand.
Dokumentationerreichbar
OCI Image Format Specification v1.1.1, Content Descriptors (externe Seite, github.com)
github.comgeprüft 10.11.2026
Die Spezifikation der Open Container Initiative für Deskriptoren, Fassung 1.1.1. Ein Deskriptor nennt Medientyp, Digest und Größe eines Inhalts. Der Digest ist ein Hash über die Bytes und kennzeichnet den Inhalt, empfohlen ist SHA-256. Der Link zeigt auf den Tag v1.1.1.
Dokumentationerreichbar
OCI Image Format Specification v1.1.1, Image Index (externe Seite, github.com)
github.comgeprüft 10.11.2026
Die Spezifikation der Open Container Initiative für den Image Index, Fassung 1.1.1. Ein Index ist ein Manifest über Manifeste: Er verweist auf je ein Manifest für eine Plattform. Der Link zeigt auf den Tag v1.1.1.
Dokumentationerreichbar
Image Manifest V 2, Schema 2 (externe Seite, github.com)
github.comgeprüft 10.11.2026
Die Beschreibung des Docker-Manifests in Schema 2 im Repository distribution, Fassung 3.1.2. Sie führt die Media-Types für Manifest, Manifest-Liste, Konfiguration und Layer und nennt als Ziel inhaltsadressierte Images. Der Link zeigt auf den Tag v3.1.2.
Dokumentationerreichbar
GGUF, die Formatbeschreibung beim Commit ffa4e8b (externe Seite, github.com)
github.comgeprüft 10.11.2026
Die Spezifikation des Dateiformats GGUF, mit dem llama.cpp und Ollama Modelle laden. Der Kopf einer Datei ist eine Liste aus Schlüsseln und Werten, darunter die Zahl der Blöcke und die Zahl der Schlüssel-Wert-Köpfe. Der Permalink zeigt auf einen festen Stand.
Dokumentationerreichbar
safetensors, die README beim Commit e246a25 (externe Seite, github.com)
github.comgeprüft 10.11.2026
Die Beschreibung des Dateiformats, in dem Hugging Face Modellgewichte verteilt. Eine Datei beginnt mit acht Byte für die Länge des Kopfs, dann folgt der Kopf als JSON mit Name, Datentyp, Form und Lage jedes Tensors, danach die Zahlen. Der Permalink zeigt auf einen festen Stand.
Originalarbeiterreichbar
k-quants, Pull Request 1684 an llama.cpp (externe Seite, github.com)
github.comgeprüft 10.11.2026
Der Pull Request, mit dem Iwan Kawrakow die k-quants in llama.cpp einbrachte, übernommen am 05.06.2023. Gewichte liegen in Superblöcken; Q4_K hat 8 Blöcke zu 32 Gewichten und kommt auf 4,5 Bit je Gewicht, Q6_K auf 6,5625. Q4_K_M nimmt für die Hälfte der Tensoren attention.wv und feed_forward.w2 den Typ Q6_K.
Dokumentationerreichbar
llama.cpp, Quelltext der Quantisierung beim Commit a4d4f2f (externe Seite, github.com)
github.comgeprüft 10.11.2026
Der Quelltext, mit dem llama.cpp beim Quantisieren jedem Tensor einen Typ zuweist, im Stand vom 09.11.2026. Bei Q4_K_M ist der Grundtyp Q4_K. Ein Teil der Schichten bekommt für attn_v und ffn_down Q6_K, der Ausgabetensor ebenfalls Q6_K. Der Permalink zeigt auf einen festen Stand.
Dokumentationerreichbar
ggml, Blockformate in ggml-common.h beim Commit a4d4f2f (externe Seite, github.com)
github.comgeprüft 10.11.2026
Die Datei, in der ggml den Aufbau seiner quantisierten Blöcke festlegt, im Stand vom 09.11.2026. Ein Block von Q4_0 fasst 32 Gewichte mit einer gemeinsamen Skala in 16 Bit. Q4_K und Q6_K bauen auf Superblöcken von 256 Gewichten auf. Der Permalink zeigt auf einen festen Stand.
Dokumentationnoch nicht geprüft
raw.githubusercontent.com
Die Datei, in der ggml seine Blockformate quantisiert und zurückrechnet, im Stand vom 09.11.2026. Bei Q4_0 zieht das Zurückrechnen von jedem 4-Bit-Wert 8 ab und multipliziert mit der Skala des Blocks, die Werte reichen also von minus 8 bis 7. Die Adresse zeigt auf einen festen Stand.
Originalarbeiterreichbar
OCP Microscaling Formats (MX) Specification, Version 1.0 (externe Seite, opencompute.org)
opencompute.orggeprüft 10.11.2026
Die Spezifikation der Microscaling-Formate im Open Compute Project vom September 2023, verfasst von Microsoft, AMD, Arm, Intel, Meta, NVIDIA und Qualcomm. Jeder Block von 32 Werten teilt eine Skala im Format E8M0, also eine Zweierpotenz. MXFP4 speichert die Werte als E2M1, MXFP8 als E4M3 oder E5M2.
Originalarbeiterreichbar
Microscaling Data Formats for Deep Learning (externe Seite, arxiv.org)
arxiv.orggeprüft 10.11.2026
Die Arbeit zu den Microscaling-Formaten vom 16.10.2023, von Forschenden bei Microsoft, AMD, Intel, Meta, NVIDIA und Qualcomm. Ein Block von Werten teilt einen Skalenfaktor, die einzelnen Werte haben nur wenige Bit. Die Spezifikation dazu ist ocp-mx-spezifikation-2023.
Ankündigung des Herstellerserreichbar
developer.nvidia.comgeprüft 10.11.2026
Der Beitrag, mit dem NVIDIA am 24.06.2025 das eigene Format NVFP4 für die Blackwell-Grafikprozessoren vorstellt. Werte liegen als E2M1 vor, je 16 Werte teilen eine Skala im Format E4M3, dazu kommt eine Skala in FP32 je Tensor. Das ergibt 4,5 Bit je Wert. Der Hersteller wirbt hier für sein Format.
Dokumentationerreichbar
MLX v0.30.0 (externe Seite, github.com)
github.comgeprüft 10.11.2026
Die Release Notes von MLX 0.30.0 vom 19.11.2025. Ab dieser Fassung kann MLX in den Formaten mxfp8 und nvfp4 quantisieren und zurückrechnen; mxfp4 kam mit 0.29.0.
Dokumentationerreichbar
mlx.core.quantize (externe Seite, ml-explore.github.io)
ml-explore.github.iogeprüft 10.11.2026
Die Doku der Funktion, mit der MLX Gewichte quantisiert, abgerufen in Fassung 0.32.4. Eine Tabelle nennt die Arten affine, mxfp4, mxfp8 und nvfp4 mit Gruppengröße und Skalentyp: mxfp4 und mxfp8 mit 32 Werten und einer Skala in E8M0, nvfp4 mit 16 Werten und einer Skala in E4M3.
Dokumentationerreichbar
MLX 0.32.4, Metal-Kernel fp4.h (externe Seite, github.com)
github.comgeprüft 10.11.2026
Der Metal-Kernel, mit dem MLX auf dem Mac einen Wert im Format E2M1 liest, in Fassung 0.32.4. Er wandelt die vier Bit in eine Zahl in float16 um. Die Skala eines Blocks von 16 Werten liest der Nachbarkernel fp_quantized.h als E4M3. Der Link zeigt auf den Tag v0.32.4.
Dokumentationerreichbar
Gemma 4 model card (externe Seite, ai.google.dev)
ai.google.devgeprüft 10.11.2026
Googles eigene Karte zur Gemma-4-Familie, auf die das Kartenverzeichnis von Google DeepMind verweist. Für das Modell 26B A4B nennt sie 25,2 Milliarden Parameter insgesamt und 3,8 Milliarden aktive, 8 von 128 Experten plus einen geteilten, 256K Token Kontext, Text und Bild als Eingabe und Apache 2.0 als Lizenz. Das Trainingsmaterial reicht nach eigener Angabe bis Januar 2025.
Dokumentationerreichbar
Gemma 4, Multi-Token Prediction overview (externe Seite, ai.google.dev)
ai.google.devgeprüft 10.11.2026
Googles Doku zu den Entwurfsmodellen von Gemma 4 für spekulatives Dekodieren. Das Entwurfsmodell teilt die Eingabetabelle der Einbettungen mit dem Zielmodell. Beim Mixture-of-Experts-Modell 26B A4B kann es bei Stapelgröße 1 auf Hardware ohne gute Parallelität ohne Gewinn bleiben, weil die Prüfung zusätzliche Experten aus dem Speicher laden muss.
Dokumentationerreichbar
v0.31.1 (externe Seite, github.com)
github.comgeprüft 10.11.2026
Die Release Notes von Ollama 0.31.1 vom 30.06.2026. Gemma 4 erzeugt auf Apple Silicon mit Multi-Token-Prediction im Mittel fast 90 Prozent mehr Token je Sekunde; gemessen hat Ollama selbst, an einem Benchmark für Coding-Agenten. Wie viele Token entworfen werden, stellt Ollama während der Ausführung selbst ein.
Dokumentationerreichbar
v0.40.0 (externe Seite, github.com)
github.comgeprüft 10.11.2026
Die Release Notes nennen den Wechsel auf MLX als Standardlaufzeit für unterstützte Modelle auf Apple Silicon.
Dokumentationerreichbar
Apple, MacBook Pro (16-inch, 2024) - Tech Specs (externe Seite, support.apple.com)
support.apple.comgeprüft 10.11.2026
Apples technische Daten des MacBook Pro mit 16 Zoll von 2024. Für den M4 Max mit 16 Prozessor- und 40 Grafikkernen nennt die Seite eine Speicherbandbreite von 546 GB/s und 36, 48, 64 oder 128 GB gemeinsamen Arbeitsspeicher für Prozessor und Grafik. Das Messgerät des Kapitels hat 64 GB. Auf diesem Gerät liefen die eigenen Messungen des Kapitels.
Originalarbeiterreichbar
SqueezeLLM: Dense-and-Sparse Quantization (externe Seite, arxiv.org)
arxiv.orggeprüft 10.11.2026
Die Arbeit zu SqueezeLLM vom 13.06.2023. Beim Erzeugen von Text mit einer einzelnen Anfrage begrenzt die Speicherbandbreite das Tempo. Die Arbeit setzt deshalb bei den Gewichten an und speichert sie mit bis zu 3 Bit.
Dokumentationerreichbar
v0.40.2 (externe Seite, github.com)
github.comgeprüft 10.11.2026
Die Release Notes von Ollama 0.40.2 vom 08.10.2026. Modelle aus früheren Fassungen werden beim ersten Start im Hintergrund umgestellt, und Ollama behält die alte Fassung als Sicherung auf der Platte. Ein Skript in den Notes sucht bei jedem Modell mit einer llamacpp-Variante das Kindmanifest mit runner ggml und übergibt dessen Digest an ollama rm. Die Sicherung bleibt nur vorübergehend, eine künftige Fassung soll sie automatisch entfernen.
Dokumentationerreichbar
Gemma releases (externe Seite, ai.google.dev)
ai.google.devgeprüft 10.11.2026
Googles Liste der Gemma-Veröffentlichungen. Gemma 4 erschien am 31.03.2026 in den Größen E2B, E4B, 31B und 26B A4B, die MTP-Entwurfsmodelle dazu am 16.04.2026.