Суть
Без кэша на каждом новом токене сеть пересчитывала бы K/V для всей последовательности заново. С кэшем — считаем K/V только для нового токена, а K/V прошлых берём из памяти.
Зачем это нужно
Генерация авторегрессивна (токен за токеном, см. Sampling Parameters); без KV-cache она была бы квадратично дорогой. Кэш переводит это в линейную работу на шаг — но платой становится память: VRAM при инференсе = веса модели + KV-cache.
Как работает
- Causal attention (Attention) гарантирует, что токен N зависит только от 0..N → K/V прошлых неизменны → кэшируемы.
- Память KV-cache растёт линейно с длиной контекста (и с числом слоёв/голов) — поэтому длинный контекст «дорогой» не только по compute, но и по VRAM (см. Context Window).
- GQA (Grouped Query Attention) уменьшает KV-cache в несколько раз (например, ×4), разделяя K/V-головы между группами Q-голов.
- На практике это определяет, сколько контекста влезет в локальную карту (см. Local LLM Deployment).
Что ломает KV-кэш в проде
Два отказа, которые видны как спайки латентности и OOM, а не как ошибки логики.
Голодание KV-кэша. Память GPU делится между весами модели, активациями и собственно KV-кэшем (в vLLM доля задаётся через gpu_memory_utilization, типично 0.9). Внезапно подросший промпт — например, добавили длинный few-shot пример на полторы тысячи токенов — при пиковом батчинге съедает свободные блоки. Дальше начинается агрессивное вытеснение чужих сессий и мгновенные ошибки нехватки видеопамяти.
Рекомпиляция CUDA-графов. Движок держит предкомпилированные графы под определённые диапазоны длин промпта. Когда новый запрос выбивается из этих бакетов, компиляция запускается прямо под нагрузкой, и латентность прыгает на 5–10 секунд.
Общее у обоих: причина не в коде агента, а в изменившемся размере промпта, поэтому обычные тесты их не ловят. Приём против — шаг профилирования в CI/CD: замерять размер токенизированного промпта и считать падение пропускной способности до деплоя, а не после.
Связано с
- Attention — кэшируются именно K/V из attention; GQA уменьшает кэш
- Context Window — длина контекста = линейный рост KV-cache в памяти
- Local LLM Deployment — VRAM = веса + KV-cache, лимит локального инференса