Prefill cache — это техника повторного использования уже посчитанных представлений префикса (общей части ввода: системного промпта, инструкций, неизменной «шапки») между запросами. В отличие от KV cache, который хранится внутри одной сессии для уже обработанных токенов, prefill cache позволяет делиться префиксом между разными запросами/пользователями, избегая повторного «разгона» модели на одинаковом начале.
Кратко: один раз «прочитали» длинный пролог — далее новые запросы стартуют уже с готовым состоянием внимания для этой части.
Префилл (Prefill cache) vs декод и где тут кэш
- Prefill — модель обрабатывает весь ввод (промпт) батчем и строит ключи/значения (K/V) для каждого токена.
- Decode — модель дописывает ответ по одному токену, обращаясь к уже накопленному KV.
- Prefill cache — хранит часть KV, соответствующую общему префиксу, чтобы не пересчитывать её снова при следующем запросе с тем же префиксом.
Чем prefill cache отличается от KV cache
| Критерий | Prefill cache (prefix/prompt) | KV cache (сеансовый) |
|---|---|---|
| Область действия | Между разными запросами/сессиями | Внутри одной последовательности/сессии |
| Содержимое | KV только для общего префикса | KV для всех уже пройденных токенов |
| Жизненный цикл | Живёт в «пуле» префиксов, переиспользуется | Растёт/сбрасывается по мере генерации |
| Экономия | Ускоряет старт и длинные «шапки» | Ускоряет пошаговую генерацию |
На практике оба механизма комплементарны и часто реализуются вместе.
Когда это даёт наибольший эффект
- Длинный system prompt и/или «инструкция бренда», одинаковая для всех диалогов.
- Шаблонные прологи RAG (например, одинаковая схема цитирования).
- Агентные пайплайны с повторяющимися «рамками ответа».
- Обработка множества коротких запросов поверх одного и того же контекстного пролога.
Если «шапка» занимает тысячи токенов, экономия префилла даёт кратный рост throughput.
Совместимость и позиционирование (важно)
Чтобы кэш «пришился», должны совпасть:
- Модель и версия (веса, токенизатор, RoPE-параметры/интерполяция).
- Позиционная система (обычно RoPE): кэшированный префикс должен начинаться с позиции 0 или использовать согласованные смещения.
- Лора/адаптеры: если подключены, префикс кэшируется под конкретным набором адаптеров.
- Токенизация: одинаковые опции разбиения (спец-токены, нормализация).
Температура, top-k/top-p и прочие параметры декодирования на совместимость не влияют — они относятся к выбору токена, а не к самим представлениям.
Где и как хранить кэш префиксов
- Paged/блочный KV-пул: разбивайте префикс на страницы (блоки) и регистрируйте карту страниц → дешёвая «пришивка» без копирования массивов.
- GPU/CPU-иерархия: «горячие» префиксы держать на GPU, «тёплые» — в пинованной CPU-памяти; редкие — выгружать.
- Идентификация префикса: детерминированный хеш от последовательности токенов (+ метаданные модели/адаптеров).
- Шардирование: крупные кэши распределяйте по устройствам; избегайте переполнения одного GPU.
Сколько памяти это ест (оценка)
Prefill cache фактически хранит подмножество KV:
bytes_prefix ≈ n_layers × len(prefix) × n_kv_heads × head_dim × 2 × sizeof(dtype)
Если префикс длиной 2k токенов и dtype fp16, память сравнима с KV такого же размера (см. формулу на странице KV cache). Экономия достигается тем, что этот объём делится между многими запросами.
Хеширование и инвалидация
- Ключ кэша: hash(tokens) ⊕ hash(model_id) ⊕ hash(adapters) ⊕ pos_scheme.
- Инвалидация при смене модели/адаптера/позиционных настроек.
- Коллизии крайне нежелательны — используйте криптостойкие хеши и храните длину/префикс для верификации.
- Ставьте TTL/LRU-политику: редкие префиксы можно вытеснять.
Типичный пайплайн с prefill cache
- Разбор запроса → детектируем общий префикс, токенизируем.
- Проверка кэша по ключу: есть ли страницы для этого префикса.
- Пришивка: связываем текущую последовательность с уже посчитанным KV префикса (позиция t=|prefix|).
- Prefill остатка (если есть частично общий пролог) и decode ответа.
- Обновление политики: счётчики обращений, LRU, миграция между уровнями памяти.
Частые ошибки и как их избежать
- Сдвиг позиций: пришили кэш, но RoPE-фазы не совпали — деградация качества. Решение: фиксируйте нумерацию позиций; общий префикс должен начинаться с нуля.
- Смешение разных адаптеров: кэш собран с LoRA v1, а запрос — с v2. Держите метаданные адаптеров в ключе.
- Фрагментация и копирования: огромные memcpy «съедают» выигрыш. Используйте блочный (paged) пул KV.
- Слишком агрессивная квантовка: INT8/FP8 для KV возможны, но проверяйте длинные ответы и логико-арифметические задачи.
- Мелкие префиксы: кэширование 50–100 токенов редко окупается — накладные расходы выше выгоды.
Оценка выигрыша (прикидка)
Пусть P — длина общего префикса, Q — длина уникальной части ввода, A — длина ответа. Время без кэша ≈ T(prefill(P+Q)) + T(decode(A)). С кэшем ≈ T(prefill(Q)) + T(decode(A)). При P ≫ Q ускорение на старте может быть кратным; общий throughput кластера растёт за счёт снятия «узкого места» префилла.
Практические пресеты
| Сценарий | Рекомендации |
|---|---|
| Общий system prompt на тысячи токенов | Вынесите в единый prefix cache, держите на GPU; инвалидация только при смене версии модели |
| Агент с шаблонными «рамками» | Разделите пролог на модули-префиксы (инструкция, формат ответа), кэшируйте модульно |
| RAG с единым стилем цитирования | Кэшируйте именно инструктивную часть, а не документы; сами документы динамичны |
| Мульти-модельный парк | Раздельные пулы по model_id; запрещайте смешение префиксов между моделями |
| Ограниченная память | INT8/FP8 для KV префикса + хранение «тёплых» страниц в CPU, промоушен по LRU |
Вопросы и ответы (FAQ)
Это увеличивает максимальное контекстное окно?
Нет. Prefill cache экономит расчёт общего префикса, но предел окна задаётся архитектурой/позиционными кодировками (см. контекстное окно).
Можно ли кэшировать «кусок середины»?
Обычно — нет: кэшируют префикс (начало). Некоторые рантаймы поддерживают модульные «префиксы», но порядок и позиции должны совпадать.
Совместим ли prefill cache с top-k/top-p/температурой?
Да. Эти параметры влияют на выбор токена в декоде, а не на совместимость префиксных представлений (см. top-k и top-p).
Это то же самое, что prefix-tuning/prompt-tuning?
Нет. Prefill cache — инференс-оптимизация. Prompt-/prefix-tuning — методы дообучения (см. fine-tuning).
