Quantisierung ist die Kunst, große Modelle kleiner zu machen, indem man die Zahlenauflösung reduziert. Statt 0.123456789 speichert man 0.12. Das spart massive Speicherplatz und Rechenzeit — mit minimalen Qualitätsverlusten.

Ein unquantisiertes Llama 3 70B braucht ~140 GB RAM. Mit Quantisierung passt es auf eine RTX 4090 mit 24 GB.


Datentypen: Von Präzision zu Kompression

FP32 (32-bit Floating Point) — Baseline

Value: 0.123456789
Memory: 4 Bytes pro Zahl

FP32 Format:
┌─ Sign Bit (1) ─┬─ Exponent (8) ─┬─ Mantissa (23) ─┐
│      0         │   10000001      │  11110010010... │
└────────────────┴────────────────┴──────────────────┘

Das ist der Standard bei Training und Vollpräzision Inference.

FP16 (16-bit Floating Point) — Halbpräzision

Value: 0.123456789 → Rounded zu ~0.1235
Memory: 2 Bytes pro Zahl → 50% Speicherersparnis

FP16 Format:
┌─ Sign (1) ─┬─ Exponent (5) ─┬─ Mantissa (10) ─┐
│     0      │     10001      │   1111010010   │
└────────────┴────────────────┴─────────────────┘

Range: 6e-8 zu 65504 (vs FP32: 1e-38 zu 3e38)

Wann? GPUs unterstützen FP16 nativ. Good Kompromiss zwischen Qualität und Speicher.

BF16 (Brain Float 16) — Google's Format

Same size (16 Bit) aber andere Aufteilung:
┌─ Sign (1) ─┬─ Exponent (8) ─┬─ Mantissa (7) ─┐
│     0      │     10000001    │   1111010      │

Vorteil: Gleicher Exponent-Range wie FP32, nur Mantissa reduziert
Result: Bessere Stabilität beim Training, ähnlich Qualität wie FP32 aber nur 2 Bytes

Nachteil: Nicht alle GPUs unterstützen BF16 nativ (RTX 30er Series muss emuliert)

Aktuelle Praxis: FP16 ist Standard, BF16 wird für Training beliebter.

INT8 (Integer 8-bit) — Erste echte Kompression

Floating Point: 0.123456789
                ↓
                Quantisieren: min=-1.0, max=1.0, 256 Levels
                ↓
Integer Index: 159 (von 0-255)
Memory: 1 Byte pro Zahl → 75% Ersparnis vs FP32, 50% vs FP16

Dequantisieren (zur Berechnung):
INT8 Value 159 → Back to ~0.124

Formel (Affine Quantisierung):

INT8_value = round(FP32_value / scale) + zero_point

Beispiel (scale=0.01, zero_point=128):
FP32: 0.5
INT8: round(0.5 / 0.01) + 128 = 50 + 128 = 178

INT4 (Integer 4-bit) — Maximum Kompression

4 Bit = 16 Levels (0-15)
Memory: 0.5 Byte pro Zahl (2 INT4s in 1 Byte)

Darstellung:
┌─ INT4 Value 1 (4 Bit) ─┬─ INT4 Value 2 (4 Bit) ─┐
│     1101 (13)          │     0111 (7)            │
└────────────────────────┴─────────────────────────┘

Quantisierungsverlauf:
Range [-1, 1] in 16 Leveln: -1.0, -0.867, -0.733, ... 0.733, 0.867, 1.0

Herausforderung: Mit nur 16 Levels ist es sehr rau. Deshalb → Group Quantization.

Group Quantization (für INT4)

Problem: Ein INT4-Level pro ganzes Gewicht ist zu grob.

Lösung: Kleine Gruppen mit jeweils eigenen min/max scales:

Gewichte: [0.1, 0.2, -0.5, 1.0 | 0.05, 0.15, 0.25, 0.95]
           └─── Group 1 ───┘   └─── Group 2 ───┘

Group 1 scale: (1.0 - (-0.5)) / 15 = 0.1
Group 2 scale: (0.95 - 0.05) / 15 = 0.06

Dann: Jede Gruppe wird mit ihrem Scale quantisiert
Result: Bessere Approximation, immer noch effizient

Group Size (typisch 32 oder 128):

  • Größere Groups = weniger Overhead (speicher für scales)
  • Kleinere Groups = bessere Qualität aber mehr scales-Overhead

Quantisierungs-Formate für LLMs

GGUF (GPT-Generated Unified Format)

Entwickelt von: Georgi Gerganov (llama.cpp) Format: Modell + Quantisierung + Metadata in einer Datei Universell: Funktioniert mit llama.cpp, Ollama, vLLM (mittlerweile)

GGUF Struktur:
┌─────────────────┐
│ Magic Number    │ "GGUF" (Datei-Signatur)
├─────────────────┤
│ Version         │ (derzeit v3)
├─────────────────┤
│ Metadata        │ model.name, tokenizer, quantization
│ (key-value)     │
├─────────────────┤
│ Tensor Data     │ Actual weights (quantisiert)
└─────────────────┘

Bits-Varianten:

Q2_K  : 2.75 bits/weight → Llama 70B ≈ 13 GB (extreme)
Q3_K  : 3.5 bits/weight → Llama 70B ≈ 18 GB (low quality)
Q4_0  : 4.0 bits/weight → Llama 70B ≈ 33 GB (popular)
Q4_K  : 4.5 bits/weight → Llama 70B ≈ 37 GB (balanced)
Q5_0  : 5.0 bits/weight → Llama 70B ≈ 41 GB (good quality)
Q6_K  : 6.6 bits/weight → Llama 70B ≈ 48 GB (high quality)
Q8_0  : 8.0 bits/weight → Llama 70B ≈ 65 GB (nearly lossless)

Vorteile:

  • Einfach zu quantisieren mit llama-cpp-python
  • Schnell zu laden und zu inferieren
  • Mehrere Quant-Optionen in 1 Datei (teilweise)

Nachteile:

  • Nur für Inference, nicht Training
  • Q2/Q3 haben spürbaren Qualitätsverlust

GPTQ (GPT Quantization)

Entwickelt von: IST Austria Ansatz: Per-Group Quantisierung mit Calibration auf Daten

Prozess:
1. Nimm Trainings-Daten (Calibration Set)
2. Pro Layer, pro Group: Finde optimale Quantisierungs-Scale
   (minimiere Fehler auf Calibration Daten)
3. Speichere Modell mit Scales
4. Inference ohne Renormalisierung nötig

Bits-Varianten:

GPTQ-4bit  : 4.0 bits/weight → Llama 70B ≈ 35 GB
GPTQ-3bit  : 3.0 bits/weight → Llama 70B ≈ 26 GB

Overhead: scales pro group (z.B. 128 Gruppe → 1 INT16 scale)

Vorteile:

  • Bessere Qualität als simple INT4 (wegen Calibration)
  • Unterstützt auch INT3
  • Aktiv entwickelt, gute Tool-Unterstützung

Nachteile:

  • Quantisierungsprozess dauert Stunden
  • Braucht Calibration-Daten
  • Weniger portable als GGUF

AWQ (Activation-Aware Quantization)

Entwickelt von: MIT Ansatz: "Nicht alle Gewichte sind gleich wichtig"

Insight: Im Matrix-Multiplikation X @ W, manche Spalten von X
sind größer (höhere Aktivierungen) → sollten präziser quantisiert sein

Algorithmus:
1. Messe Aktivierungen pro Kanal
2. Quantisiere weniger aktive Kanäle aggressiv
3. Quantisiere wichtige Kanäle konservativ
Result: Besseres Qualität/Größe Verhältnis

Bits-Varianten:

AWQ-4bit   : 4.0 bits/weight → Llama 70B ≈ 35 GB
             Aber bessere Qualität als GPTQ

Vorteile:

  • Best-in-class Qualität für INT4
  • Schneller Quantisierungsprozess (Minuten, nicht Stunden)
  • Gutes Tool-Support (AutoAWQ)

Nachteile:

  • Neueres Format, weniger Tools als GPTQ
  • Tool-Support nicht überall (llama.cpp Support entwickelt sich noch)

EXL2 (ExLlamaV2 Format)

Entwickelt von: turboderp (ExLlama) Ansatz: 4-bit quantization mit variabler Bit-Länge pro Tensor

EXL2 Idee:
- Verschiedene Layer/Tensoren brauchen unterschiedliche Präzision
- Pro Tensor: Variable bits (z.B. Layer 1: 5-bit, Layer 2: 4-bit)
- Besser als uniform 4-bit, aber komplexer zu implementieren

Praktisch:

EXL2-3.0bpw : 3.0 bits/weight → Llama 70B ≈ 23 GB (wild!)
EXL2-4.5bpw : 4.5 bits/weight → Llama 70B ≈ 35 GB (usual)

Besonderheiten:

  • Nur für ExLlama/ExLlama2 Inference
  • Extrem schnell (optimierte CUDA Kernel)
  • Höhere Qualität als GGUF Q4 bei gleicher Größe

Nachteile:

  • Spezialisiert auf ExLlama (nicht überall verwendbar)
  • Kleinerer Ökosystem als GGUF/GPTQ

Vergleich-Tabelle

Format Bits Ggf. 70B Qualität Speed Tool Support Portabilität
FP32 32 140 GB Reference Slow Alle Überall
GGUF Q4_0 4.0 33 GB Gut Schnell Excellente Überall
GGUF Q5_0 5.0 41 GB Sehr Gut Schnell Excellente Überall
GPTQ-4bit 4.0 35 GB Sehr Gut Schnell Gut Llama.cpp, vLLM
AWQ-4bit 4.0 35 GB Excellente Schnell Gut Ollama, vLLM
EXL2-4.5 4.5 35 GB Excellente Sehr Schnell Spezialisiert ExLlama only
GGML ~4 33 GB OK Langsam Veraltet Legacy-Systeme

Quantisierungs-Qualität messbar

Benchmarks (Typical Test Results)

Getestet auf: Llama 3 70B, Hellaswag und MMLU Benchmarks

Original (FP32):
- MMLU:    81.2%
- Hellaswag: 88.3%

GGUF Q4_0:
- MMLU:    80.9% (↓ 0.3%)
- Hellaswag: 87.8% (↓ 0.5%)

GPTQ-4bit:
- MMLU:    81.0% (↓ 0.2%)
- Hellaswag: 88.1% (↓ 0.2%)

AWQ-4bit:
- MMLU:    81.1% (↓ 0.1%)
- Hellaswag: 88.2% (↓ 0.1%)

EXL2-4.5:
- MMLU:    81.0% (↓ 0.2%)
- Hellaswag: 88.0% (↓ 0.3%)

Fazit: 4-bit Quantisierung hat <1% Qualitätsverlust bei guten Methoden!

Perplexity (ein Maß für sprachliche Qualität)

Perplexity = e^(-(1/N) * Σ log P(w_i))

Niedriger = besser

FP32:          7.2
GGUF Q4_0:     7.4 (+2.7%)
GGUF Q3_K:     8.1 (+12.5%)
GPTQ-4bit:     7.3 (+1.4%)
AWQ-4bit:      7.2 (~0%)

Mit llama.cpp quantisieren (praktisch)

Installation

git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
make

# oder via homebrew (macOS)
brew install llama-cpp

Schritt 1: Modell zu GGML konvertieren

# HuggingFace Modell downloaden
python3 -m huggingface_hub download meta-llama/Llama-2-7b-chat \
  --local-dir ./llama-2-7b-chat-hf

# Zu GGML konvertieren
python3 convert.py ./llama-2-7b-chat-hf

# Output: ggml-model-f32.gguf (Vollpräzision, gigantisch)

Schritt 2: Quantisieren

# Q4_0 quantisieren (4-bit)
./quantize ./ggml-model-f32.gguf ./ggml-model-q4_0.gguf q4_0

# Q5_0 (5-bit, bessere Qualität)
./quantize ./ggml-model-f32.gguf ./ggml-model-q5_0.gguf q5_0

# Q3_K (3.5-bit, aggressiv)
./quantize ./ggml-model-f32.gguf ./ggml-model-q3_k_m.gguf q3_k_m

# Dauer: 5-30 Min je nach Modellgröße

Schritt 3: Testen

# Interaktiv nutzen
./main -m ./ggml-model-q4_0.gguf -n 128 -i

# "# So long and thanks for all the fish" eingeben, Enter drücken
# Modell antwortet

Via Python (AutoGGUF)

from huggingface_hub import snapshot_download
from llama_cpp import Llama

# Download und quantisieren automatisch
llm = Llama.from_pretrained_gpt4all(
    repo_id="TheBloke/Llama-2-7b-Chat-GGUF",
    filename="llama-2-7b-chat.Q4_K_M.gguf",
    verbose=False
)

response = llm("Erkläre mir Quantisierung in 100 Worten", max_tokens=100)
print(response["choices"][0]["text"])

Welches Format für deine Use-Case?

Lokal auf Consumer-GPU (RTX 4090, 24 GB)

Ideal: GGUF Q4_0 oder Q5_0
Grund: Simple, portable, guter Tool-Support
Tool: llama.cpp, Ollama, LM Studio

Lokal auf schwacher Hardware (8 GB)

Ideal: GGUF Q2_K oder Q3_K (für kleine Modelle wie 7B/13B)
Grund: Passt in RAM
Tool: llama.cpp, Ollama
Warnung: Q2_K hat spürbaren Qualitätsverlust!

Cloud/Server mit starker GPU (RTX 6000, 48 GB)

Ideal: GPTQ-4bit oder AWQ-4bit
Grund: Bessere Qualität bei gleichem Speicher
Tool: vLLM (mit GPTQ/AWQ Support)

Maximum Speed (Real-time Inference)

Ideal: EXL2-4.5
Grund: ExLlama2 hat extrem optimierte CUDA Kernel
Tool: ExLlama2 / oobabooga WebUI
Kost: Nur für ExLlama verfügbar, nicht überall

Größtmögliche Modelle auf kleinem Speicher

Ideal: GGUF Q2_K oder EXL2-3.0bpw
Grund: Extremste Kompression
Tool: llama.cpp oder ExLlama2
Warnung: Qualität ist fragwürdig, NUR für Experimente

Performance-Realitäten (2026 Daten)

Speicherverbrauch (Llama 3 70B)

FP32:       138 GB
FP16:        69 GB
GGUF Q4_0:   33 GB (76% Ersparnis!)
GGUF Q3_K:   25 GB
EXL2-4.5:    35 GB (auch mit Caching)

Inferenz-Speed (Tokens pro Sekunde, RTX 4090)

GGUF Q4_0:   120 tokens/s
GPTQ-4bit:    95 tokens/s
AWQ-4bit:     98 tokens/s
EXL2-4.5:    145 tokens/s (mit spezialisiertem Kernel)

Quality Loss (Benchmark durchschnitt)

GGUF Q4_0:   0.8% Qualitätsverlust
GGUF Q3_K:   3.5%
GPTQ-4bit:   0.3%
AWQ-4bit:    0.1%
EXL2:        0.2%

Häufige Fehler bei Quantisierung

Fehler 1: Falsches Quantisierungs-Format für Use-Case

Problem: "Ich nehme GGUF für Produktion, muss maximale Speed"
Lösung: EXL2-4.5 oder GPTQ mit vLLM

Fehler 2: Aggressive Quantisierung ohne Testen

Problem: "Llama 70B → Q2_K, spart viel Speicher!"
Resultat: Modell ist dumm, gibt Nonsense
Lösung: Q4_0 mindestens, oder Q3_K mit Tests

Fehler 3: Quantisierungs-Tool ignorieren

Problem: "Ich quantisiere mit llama.cpp auf Llama-3 der gemacht ist für GPTQ"
Resultat: Schlechte Kompatibilität
Lösung: Check HuggingFace model card welcher Quantisierungs-Typ empfohlen

Fehler 4: Falsche Bit-Tiefe für Anforderung

Problem: "Ich brauche Präzision für medizinisches NLP, nehme Q2_K"
Resultat: Unzuverlässige Antworten
Lösung: Mindestens Q4_K, eher Q5_0 oder GPTQ-4bit

Quantisierung ist das Wundermittel um große Modelle praktisch zu machen. Mit GGUF Q4_0 sparst du 76% Speicher mit <1% Qualitätsverlust. Das ist eine der besten Investitionen beim LLM-Einsatz.