Что такое PagedAttention
PagedAttention — ключевая технология vLLM, которая решает проблему фрагментации памяти KV-cache. Традиционные подходы выделяют непрерывный блок памяти для каждого запроса, что приводит к фрагментации и неэффективному использованию GPU-памяти.
PagedAttention использует концепцию виртуальной памяти из ОС: KV-cache разбивается на фиксированные блоки, которые могут быть распределены не непрерывно в памяти GPU. Каждый запрос «владеет» виртуальной последовательностью блоков, а физическое размещение решает runtime.
Какую проблему это решает
KV-cache — это скрытые состояния attention, которые модель накапливает по мере генерации. Для 27B-модели с 256K контекста KV-cache одного запроса занимает порядка десятков гигабайт. Без PagedAttention runtime обязан зарезервировать максимально возможную длину генерации на каждый запрос заранее:
- Запрос с фактической генерацией в 500 токенов занимает память под 4K токенов — 8x перерасход.
- Освобождённые «хвосты» не возвращаются в общий пул — память фрагментируется.
- Через несколько часов работы свободные блоки разбросаны, и новые запросы с длинным контекстом не помещаются, хотя суммарно памяти хватает.
По данным авторов vLLM, на смешанной нагрузке PagedAttention даёт 2–4x throughput по сравнению с наивной аллокацией — именно за счёт устранения перерасхода и фрагментации.
Как это работает
- Блокировка: KV-cache разбивается на блоки фиксированного размера (по умолчанию 16 токенов, настраивается).
- Виртуальное адресование: каждый запрос имеет таблицу страниц, которая мапит виртуальные блоки на физические.
- Гибкое распределение: блоки могут быть распределены в любом месте памяти GPU; аллокация — из общего пула свободных блоков.
- Освобождение: завершённый запрос возвращает блоки в пул по одному, без «дыр».
Дополнительный эффект: блоки можно шарить между запросами — это основа prefix caching (ниже).
Prefix caching
Если несколько запросов начинаются с одинакового префикса (system prompt, общий контекст), vLLM может переиспользовать уже вычисленные KV-блоки вместо повторного prefill:
vllm serve model --enable-prefix-caching
Для агентных нагрузок это критично: агент шлёт один и тот же system prompt + историю сотнями раз в час. Каждый повторный запрос без prefix caching пересчитывает prefill на десятки тысяч токенов; с ним — берёт блоки из кэша.
В нашем референс-деплое prefix-aware routing на уровне балансировщика поднял KV-cache hit rate с 12% до 34% — это прямой прирост throughput без изменения железа (подробнее — часть 4 серии «Наш опыт»).
Настройка в vLLM
--block-size— размер блока в токенах (по умолчанию 16). Меньший блок — меньше перерасход на «хвост», но больше накладных расходов на таблицы страниц.--gpu-memory-utilization— доля GPU-памяти, доступной под KV-cache (по умолчанию 0.9). В нашем конфиге — 0.92.--enable-prefix-caching— включение переиспользования общих префиксов.
Когда это важно
PagedAttention работает всегда (это не опция vLLM), но его эффект максимален при:
- Смешанной нагрузке — запросы разной длины и длительности генерации.
- Высокой загрузке — чем больше одновременных запросов, тем сильнее фрагментация без него.
- Повторяющихся префиксах — агенты, RAG с общим system prompt, чат-боты.
Смежные материалы: Continuous Batching, Observability (KV-cache usage — ключевая метрика).
Что мы видели в референс-деплое
На 2×RTX 3090 с 256K контекстом KV-cache съедает ~18GB из 48GB: блоки под 256K на 2 последовательности — это основной потребитель памяти. Именно поэтому в финальном конфиге --max-num-seqs 2: PagedAttention позволяет уложить 256K×2 в доступную память, но не три. Полный разбор — часть 3 серии.
Вывод
PagedAttention — не «фича», а фундамент, на котором держится throughput vLLM. При тюнинге смотрите на два числа: KV-cache usage % (заполненность пула блоков) и prefix cache hit rate — это прямые индикаторы, насколько эффективно память работает на вашу нагрузку.