Расчёт размера KV-кэша
- title
- Расчёт размера KV-кэша
- type
- concept
- summary
- Память на токен = 2 × KV-heads × head-dim × слои × байты/элемент; переход на q4_0 позволяет бесплатно удвоить контекст
- tags
- llm, local-models, context-window
- created
- 2026-05-13
- updated
- 2026-07-29
- lang
- ru
- translation_of
- kv-cache-sizing
- source_updated
- 2026-07-29
- translated
- 2026-09-01
- translator
- lllm/antigravity/gemini-3.7-flash-medium
Каждый токен в контексте требует памяти для хранения состояния attention - векторов key и value для каждой головы внимания на каждом слое. Формула простая:
KV bytes per token = 2 × num_kv_heads × head_dim × num_layers × bytes_per_element
Множитель 2 - это K плюс V. Размер элемента зависит от типа кэша: f16 занимает 2 байта, q8_0 - 1 байт, q4_0 - полбайта. Снижение точности кэша вдвое уменьшает расход памяти на токен при незначительном влиянии на качество.
Почему расход так сильно различается между моделями
Архитектура имеет большее значение, чем количество параметров. Две модели из тестов Вячеслава:
| Модель | KV heads | Head dim | Слои | KV на токен (q4_0) |
|---|---|---|---|---|
| Qwen 3.6 35B | 2 | 128 | 40 | ~10 KB |
| Gemma 4 26B | ~7 avg* | 176 | 30 | ~36 KB |
*У Gemma 4 нерегулярная структура: на большинстве слоёв по 8 голов KV, но на каждом шестом - всего 2, что в сумме даёт 210 голов на 30 слоёв.
Большая размерность головы и большее среднее число голов делают KV-кэш Gemma примерно в 4 раза дороже на токен, чем у Qwen 3.6, несмотря на меньшее общее число параметров. На контексте в 256K это имеет большое значение: при 262K токенов запас VRAM под KV для Gemma превышает объём, который занимает вся модель в квантовании Q4.
Замена q8_0 -> q4_0
Тип кэша по умолчанию во многих примерах для llama.cpp - q8_0 (1 байт на элемент). Переход на q4_0 (0.5 байта на элемент) вдвое сокращает размер кэша практически без измеримого падения качества: Вячеслав отмечает, что ни одна из моделей не потеряла связность при входах более 200K токенов. В сочетании с выгрузкой большего числа экспертов в RAM через `--n-cpu-moe` именно это позволило ему уместить заявленный максимум в 256K токенов для каждой модели на 16 GB.
Пример расчёта бюджета на 16 GB
Для Qwen 3.6 35B на контексте 256K на RTX 5070 Ti 16 GB:
| Настройка | --n-cpu-moe |
VRAM в простое | Пик при ~238K токенов |
|---|---|---|---|
| 32K контекст, q8_0 | 17 | 14.8 GB | - |
| 128K контекст, q4_0 | 20 | 14.0 GB | 14.1 GB |
| 256K контекст, q4_0 | 23 | 14.1 GB | 14.7 GB |
Для Gemma 4 26B на контексте 262K:
| Настройка | --n-cpu-moe |
VRAM в простое | Пик при ~245K токенов |
|---|---|---|---|
| 32K контекст, q8_0 | 8 | 14.8 GB | - |
| 131K контекст, q4_0 | 10 | 14.1 GB | 14.5 GB |
| 262K контекст, q4_0 | 12 | 14.4 GB | 15.3 GB |
Пик у Gemma в 15.3 GB оставляет минимальный запас: снижение --n-cpu-moe до 11 приводит к OOM на 262K. Меньшая стоимость KV у Qwen позволяет пиковому потреблению оставаться с запасом в пределах 15 GB даже при полных 256K.
Чем приходится платить
Увеличение --n-cpu-moe означает, что больше экспертов обрабатывается через PCIe, поэтому генерация немного замедляется. Для Gemma 4 разница между --n-cpu-moe=8 и --n-cpu-moe=12 невелика (на этом железе производительность модели упирается в вычисления). Для Qwen 3.6 замедление более заметно, но взамен даёт восьмикратный контекст.
За рамками q4_0 - TurboQuant для KV-кэша
Семейство методов сжатия KV-кэша по схеме "вращение, затем квантование" (random-rotation-quantization) совпадает по recall с полной точностью при 4-кратном сжатии. Сравнение на Llama-3.1-8B при одинаковом бюджете памяти:
| Метод | NiaH recall |
|---|---|
| Полный кэш (FP16) | 0.997 |
| KIVI (целочисленный с поблочными шкалами) | 0.981 |
| TurboQuant | 0.997 |
Форк llama-cpp-turboquant для llama.cpp предоставляет кодовую книгу TurboQuant через параметры --cache-type-k turbo4 --cache-type-v turbo3. В треде на Reddit показано, как Qwen3.6-35B-A3B на контексте 131K помещается в 8 GB на GTX 1070 отчасти благодаря тому, что turbo4 снижает затраты на KV до ~590 MB против ~720 MB при q4_0. Бюджет по байтам похож, но recall ощутимо выше. Сама конструкция описана в interactive-turboquant.
ik_llama также поддерживает квантование KV-кэша в Q6 - это другая точка на кривой размер/качество, которая работает только в этом форке.
Ссылки
- moe-cpu-offload - второй рычаг в бюджете на 16 GB
- mixture-of-experts - почему MoE делает возможным столь точный расчёт бюджета
- local-llm-16gb-vram-tests - исходная статья и общий контекст
- random-rotation-quantization - семейство TurboQuant, следующий шаг после q4_0
- interactive-turboquant - руководство от arkaung'а по конструкции с вращением
- kimi-delta-attention - полностью обходит эту арифметику: состояние linear-attention имеет фиксированный размер независимо от длины контекста
- prompt-caching-in-agents - то же состояние между запросами, а не внутри одного: кто держит его активным, как долго и сколько стоит пересчёт при промахе