Что такое 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 по сравнению с наивной аллокацией — именно за счёт устранения перерасхода и фрагментации.

Как это работает

  1. Блокировка: KV-cache разбивается на блоки фиксированного размера (по умолчанию 16 токенов, настраивается).
  2. Виртуальное адресование: каждый запрос имеет таблицу страниц, которая мапит виртуальные блоки на физические.
  3. Гибкое распределение: блоки могут быть распределены в любом месте памяти GPU; аллокация — из общего пула свободных блоков.
  4. Освобождение: завершённый запрос возвращает блоки в пул по одному, без «дыр».

Дополнительный эффект: блоки можно шарить между запросами — это основа 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 — это прямые индикаторы, насколько эффективно память работает на вашу нагрузку.

← Контакты Continuous Batching →