Глава 2 — Проблема KV-кэша
Второй пост поглавного разбора LLM Primer VI: Scaling AI Systems. Глава, называющая структуру данных, которая съедает VRAM каждой serving-системы раньше, чем до неё вообще успевают добраться веса.
Зачем эта глава существует
Авторегрессионный цикл главы 1 избегает квадратичной работы, запоминая. На каждом шаге декодинга модели нужно смотреть на все предыдущие токены, и делать это с нуля означало бы перезапускать весь prefill на каждой итерации — N-кратный множитель по длине генерации. KV-кэш — то рабочее пространство, что экономит эту арифметику. Он хранит K- и V-проекции по каждому токену на каждом слое, так что более поздние токены считают только свои K и V, а более ранние читают обратно. Кэш — причина, по которой декодинг остаётся примерно O(N), а не O(N²). Он же — в каждой продакшен-системе, которую я видел, — крупнейший единичный потребитель VRAM. Глава 2 обходит формулу, определяющую его размер, архитектурные варианты, ужимающие его, и проблему фрагментации, которая ломает наивный способ его распределить.
2.1 Формула, определяющая размер кэша
KV-память для одной последовательности равна 2 × L × H_kv × D × S × bytes: два тензора (K и V), L слоёв, H_kv key/value-голов, размерность головы D, длина последовательности S и байты на элемент. Умножьте на размер батча — получите число уровня флота. Каждая ось — мультипликативная. Llama-3-70B при L=80, H_kv=8 (GQA), D=128, при S=8 192 и BF16 держит примерно 40 ГБ кэша на последовательность — до батча. При батче 32 один кэш подходит к 1,3 ТБ, что в несколько раз больше самих весов и в несколько раз больше VRAM у H100. Llama-2-70B, последняя крупная MHA-модель, имеет H_kv=64 вместо 8, и её кэш в восемь раз больше при той же конфигурации. Формула — не любопытный факт; это число определяет, сколько параллельных пользователей может держать чип. Все прочие бюджеты памяти на плате — активации, оверхед фреймворка, временные буферы — должны уместиться вокруг него.
2.2 MHA, GQA и MQA — это выбор размера кэша
H_kv — тот член, который современные архитектуры сознательно ужимают. Multi-head attention (MHA) держит по одной K/V-голове на каждую query-голову; кэш толстый, качество максимальное, каждая голова специализируется на своём внимании. Multi-query attention (MQA) сводит всё к одной общей K/V-голове; кэш сжимается в H раз, но головы теряют специализацию и на длинных контекстах теряется измеримое качество. Grouped-query attention (GQA), появившаяся в 2023 году и ставшая доминирующим выбором для Llama-3, Mistral, Mixtral, Qwen и DeepSeek, разбивает query-головы на G групп, делящих K и V; типичное G = H/8 даёт восьмикратное сокращение кэша при потере качества, которую бенчмарки не могут надёжно увидеть. GQA не бесплатна — она также сокращает число параметров K/V-проекции, и этот бюджет перераспределяется в другие места модели, — но эмпирически перераспределение почти никогда не вредит. MLA (multi-latent attention, DeepSeek-V2) идёт дальше с латентным кэшем низкого ранга; это исследовательское направление, но продакшен-развёртывания в 2026 году доминантно GQA.
2.3 Наивное распределение выбрасывает большую часть бюджета
Очевидный способ распределить KV-память — зарезервировать под каждую последовательность непрерывный слэб размером с максимально возможную длину — рушится при встрече с реальным трафиком. Большинство запросов завершается далеко до максимума; зарезервированный хвост — мёртвая память. На Llama-3-70B с пределом в 32K генерация в 1 000 токенов теряет 31 слэб KV-кэша. Батч 32 при пределе 8K и средней длине 800 оставляет примерно 90 процентов зарезервированного KV-кэша неиспользованными в любой момент. Хуже, разметка негибка: вновь пришедший запрос не может использовать неиспользованный хвост другой последовательности, потому что тот уже закреплён. Параллельность падает до того, что позволяет худший бюджет, а не до того, что мог бы поддержать средний трафик. Проблема — внутренняя фрагментация, тот же режим отказа, который операционные системы решили пагингом в 1960-х. Глава 8 показывает, как PagedAttention переносит это решение сюда.
Что подготавливает глава 2
Формула кэша и её оси будут всплывать всякий раз, когда более поздним главам приходится рассуждать о том, сколько пользователей помещается на одном GPU. Глава 3 использует её, чтобы объяснить, почему при выборе serving-GPU ёмкость VRAM важнее FLOP/s. Глава 7 использует её, чтобы объяснить, почему continuous batching ограничен KV-кэшем, а не моделью. Глава 8 использует её, чтобы обосновать PagedAttention, вытеснение H2O и префиксное кэширование — три приёма, чья цель — заставить кэш вести себя как страничная виртуальная память, а не как слэб зарезервированных байтов. Формула — это грамматика всех дальнейших аргументов книги о памяти.
Дальше — Глава 3: Дата-центровые GPU для генеративного ИИ. Кремний, который должен удерживать и веса, и KV-кэш, прочитанный по механизму, а не по спецификации.