# Инференс: KV-cache, квантизация, спекулятивный декодинг

> Инференс LLM: KV-cache, квантизация и speculative decoding — куда уходит VRAM и как ускоряют генерацию токенов в проде.

Раздел: [LLM: обучение и инференс](https://ml-book.com/s/llm/) · Страница темы: https://ml-book.com/t/inference/ · Обновлено: 2026-09-16 · Источник: ml-book.com, учебник делается сообществом

## Интуиция: почему это дорого

LLM авторегрессивна: чтобы написать ответ из 500 токенов, нужно 500 последовательных прогонов модели — каждый следующий токен зависит от предыдущих, распараллелить по времени нельзя. При этом у запроса две очень разные фазы:

- **Prefill** — обработка промпта. Все токены промпта известны заранее, их можно прогнать через модель параллельно одной матричной операцией. GPU загружен вычислениями (compute-bound), фаза быстрая.
- **Decode** — генерация. По одному токену за шаг: ради каждого токена приходится прокачать через чип все веса модели и весь кэш. Арифметики мало, трафика памяти много — фаза memory-bound, и именно она определяет скорость генерации.

Отсюда две главные метрики сервинга: **TTFT** (time to first token — в основном цена prefill) и **tokens/s** (скорость decode).

## KV-cache: не считать одно и то же

Внимание (attention) на каждом шаге смотрит на все прошлые токены — ему нужны их ключи K и значения V. Наивно их можно пересчитывать заново на каждом шаге, но они не меняются! KV-cache (кэш ключей и значений) сохраняет K и V всех обработанных токенов, и на новом шаге считаются K/V только одного нового токена. Стоимость шага падает с квадратичной по длине до линейной.

Платим памятью. Размер кэша растёт линейно с длиной контекста:

`память = слои × KV-головы × d_{head} × 2 (K и V) × длина × байт/число`

Для 7B-модели (32 слоя, 32 головы по 128 измерений, fp16) это ≈ 0.5 МБ на токен: контекст в 32k токенов съедает ~16 ГБ — сопоставимо с самими весами. Поэтому «большое контекстное окно» — это не бесплатная фича, а прямые затраты памяти и трафика; архитектуры вроде GQA (общие KV-головы) придуманы как раз чтобы уменьшить этот кэш.

> **💡 Ключевая мысль**
>
> Decode упирается не в FLOPs, а в пропускную способность памяти: на каждый токен через чип гонятся все веса и весь KV-cache. Почти все трюки инференса — квантизация, GQA, спекулятивный декодинг, батчинг — так или иначе экономят именно трафик памяти на один сгенерированный токен.

> 🎛 Интерактивная визуализация — на странице темы: https://ml-book.com/t/inference/

## Квантизация: жмём веса

Раз decode упирается в трафик памяти, очевидный ход — сделать веса меньше. Квантизация (quantization) переводит веса из fp16 в int8 или int4: модель занимает в 2–4 раза меньше памяти, и на каждый токен через чип гоняется в 2–4 раза меньше байтов — генерация ускоряется почти пропорционально. Цена — небольшая потеря качества; методы вроде **GPTQ** и **AWQ** подбирают квантизацию аккуратно (калибровка на данных, защита важных весов), так что для int4 деградация часто едва заметна. Квантизуют и KV-cache — экономия та же по смыслу.

## Спекулятивный декодинг и батчинг

Спекулятивный декодинг (speculative decoding) обходит последовательность decode хитростью: маленькая быстрая draft-модель предлагает сразу несколько токенов вперёд, а большая модель проверяет их все одним параллельным прогоном (как prefill). Совпавший префикс принимается, первый несовпавший токен большая модель ставит своим. Специальное правило принятия гарантирует, что итоговое распределение — в точности распределение большой модели: ускорение в 2–3 раза *без* потери качества, если draft часто угадывает.

На сервере считают не латентность одного запроса, а пропускную способность. Батчинг объединяет запросы: веса читаются из памяти один раз на весь батч, стоимость на запрос падает. **Continuous batching** добавляет и убирает запросы из батча на каждом шаге, не дожидаясь, пока все закончат. **vLLM** с **PagedAttention** хранит KV-cache постранично, как виртуальную память ОС, убирая фрагментацию и позволяя набивать в GPU намного больше параллельных запросов.

> **⚠️ Подводный камень**
>
> Легко забыть, что KV-cache живёт *на каждый запрос*. Один пользователь с контекстом 32k у 7B-модели — это ~16 ГБ кэша; 10 таких пользователей параллельно не поместятся ни в один GPU, сколько ни квантизуй веса. Планируя сервинг, память считают как «веса + KV-cache × размер батча × длина контекста», и второе слагаемое часто главное.

> **🎤 На собеседовании**
>
> - «Почему decode медленнее prefill?» — prefill параллелен по токенам и compute-bound; decode — по токену за шаг, упирается в трафик памяти (веса + кэш на каждый токен).
> - «Что хранит KV-cache и сколько он весит?» — ключи и значения всех прошлых токенов по всем слоям и головам; размер линеен по длине контекста (≈0.5 МБ/токен у 7B в fp16).
> - «Спекулятивный декодинг портит качество?» — нет: правило принятия сохраняет распределение большой модели, ускорение берётся из параллельной проверки.
> - «Как оценивать сервинг?» — TTFT, tokens/s на запрос и суммарный throughput; continuous batching и PagedAttention повышают именно throughput.

## Связанные темы

- [Сэмплирование: temperature, top-k, top-p](https://ml-book.com/t/sampling/)
- [Fine-tuning: SFT, LoRA, PEFT](https://ml-book.com/t/finetuning/)
- [Дизайн ML-систем на собеседовании](https://ml-book.com/t/ml-system-design/)
- [Мониторинг и дрифт данных](https://ml-book.com/t/monitoring-drift/)

---

Интерактив, тест из 12 вопросов и карточки терминов — на странице темы: https://ml-book.com/t/inference/
Весь учебник в markdown: https://ml-book.com/llms-full.txt · Оглавление для агентов: https://ml-book.com/llms.txt
