Оптимізація KV-кешу: ефективне використання пам'яті для продакшн LLM
Оновлено 11 грудня 2025 року
Оновлення за грудень 2025: Традиційний інференс витрачає 60-80% пам'яті KV-кешу через фрагментацію та надмірне виділення. PagedAttention від vLLM зменшує втрати до 4%, забезпечуючи 2-4-кратне підвищення пропускної здатності. Модель 70B з контекстом 8K потребує ~20 ГБ кешу на запит, ~640 ГБ для батчу з 32. KV-кеш тепер часто перевищує вагу моделі за споживанням пам'яті. Техніки оптимізації дозволяють працювати з довшими контекстами та більшими батчами на наявному обладнанні.
Системи LLM-інференсу витрачають 60-80% виділеної пам'яті KV-кешу через фрагментацію та надмірне виділення.¹ Ці втрати безпосередньо призводять до зниження пропускної здатності, вищих витрат та штучних обмежень довжини контексту. PagedAttention, представлений vLLM, скоротив втрати KV-кешу до менш ніж 4%, забезпечивши 2-4-кратне підвищення пропускної здатності, що трансформувало економіку продакшн-інференсу.² Розуміння технік оптимізації KV-кешу допомагає організаціям максимізувати використання GPU та обслуговувати більше користувачів на існуючій інфраструктурі.
Управління KV-кешем стало критичним вузьким місцем для продакшн-розгортань LLM. Споживання пам'яті зростає лінійно з довжиною послідовності та розміром батчу, швидко вичерпуючи навіть GPU з великим обсягом пам'яті, як-от H100 та H200. Опанування технік оптимізації кешу дозволяє працювати з довшими контекстами, більшими батчами та забезпечує економічніший інференс у масштабі.
Чому KV-кешування важливе
Трансформерні моделі обчислюють увагу по всіх попередніх токенах при генерації кожного нового токена. Без кешування генерація 1 000 токенів вимагає повторного обчислення уваги з нуля 1 000 разів — квадратично збільшуючи вартість із довжиною послідовності.
Рішення KV-кешування: Зберігати тензори ключів і значень з попередніх токенів, повторно використовуючи їх для подальших обчислень уваги. Кожен новий токен обчислює увагу відносно кешованих значень замість їх повторної генерації.
Вплив на пам'ять: Модель з 70B параметрами, що генерує 8 192 токени з батчем 32, потребує приблизно 40-50 ГБ пам'яті лише для KV-кешу — часто перевищуючи самі ваги моделі.³
Проблема масштабування: Пам'ять KV-кешу зростає як:
Пам'ять = batch_size × seq_length × num_layers × 2 × hidden_dim × precision_bytes
Для Llama 3.1-70B з FP16: - Кеш на токен: ~2,5 МБ - Контекст 8K: ~20 ГБ на запит - Батч з 32: ~640 ГБ загального KV-кешу
PagedAttention: фундаментальна оптимізація
PagedAttention від vLLM революціонізував управління KV-кешем, обробляючи пам'ять GPU як віртуальну пам'ять операційної системи:⁴
Як це працює
Традиційне виділення: Резервування суміжних блоків пам'яті для максимально можливої довжини послідовності. Максимальний контекст 4K виділяє кеш на 4K навіть для запитів із 100 токенів, витрачаючи 97,5% зарезервованої пам'яті.
Сторінкове виділення: Поділ KV-кешу на блоки фіксованого розміру (сторінки). Виділення сторінок на вимогу в міру зростання послідовностей. Звільнення сторінок після завершення послідовностей.
Таблиця відображення блоків: Подібно до таблиць сторінок ОС, PagedAttention підтримує відображення між логічними позиціями послідовності та фізичними адресами пам'яті. Послідовності бачать безперервну пам'ять, тоді як фізичне зберігання залишається несуміжним.
Вплив на продуктивність
- Втрати пам'яті: 60-80% → менше 4%
- Пропускна здатність: 2-4-кратне покращення порівняно з традиційним виділенням
- Фрагментація пам'яті: практично усунена⁵
Реалізація у vLLM
from vllm import LLM, SamplingParams
# PagedAttention увімкнено за замовчуванням
llm = LLM(
model="meta-llama/Llama-3.1-70B-Instruct",
tensor_parallel_size=4,
gpu_memory_utilization=0.90, # Використовувати 90% пам'яті GPU
max_model_len=32768,
)
vLLM автоматично керує виділенням, звільненням та спільним використанням сторінок без явної конфігурації.
Кешування префіксів та спільне використання пам'яті
PagedAttention дозволяє ефективне спільне використання пам'яті між запитами зі спільними префіксами:
Спільні системні промпти: Коли кілька запитів використовують ідентичні системні промпти, фізичні сторінки, що зберігають ці токени, використовуються спільно, а не дублюються.
Автоматичне кешування префіксів: Automatic Prefix Caching (APC) від vLLM виявляє спільні префікси між запитами та автоматично використовує спільні блоки KV-кешу:
llm = LLM(
model="meta-llama/Llama-3.1-8B-Instruct",
enable_prefix_caching=True,
)
Вплив на продакшн: Застосунки з постійними системними промптами або повторюваним контекстом (RAG зі спільними документами, few-shot приклади) отримують значну економію пам'яті та зменшення затримки. Коефіцієнт влучень у кеш 87%+ досяжний при добре структурованих промптах.⁶
Квантизація KV-кешу
Стиснення значень KV-кешу зменшує вимоги до пам'яті ціною незначної втрати точності:
FP8 KV-кеш
GPU Hopper та Blackwell підтримують нативний FP8 KV-кеш:
# vLLM FP8 KV-кеш
llm = LLM(
model="meta-llama/Llama-3.1-70B-Instruct",
kv_cache_dtype="fp8",
)
FP8 вдвічі зменшує пам'ять KV-кешу порівняно з FP16 з мінімальним впливом на якість для більшості застосунків. Ця оптимізація стає необхідною для інференсу з довгим контекстом, де кеш домінує в споживанні пам'яті.
INT4 KV-кеш
Експериментальна підтримка 4-бітного KV-кешу додатково зменшує пам'ять:⁷ - Зменшення пам'яті: у 4 рази порівняно з FP16 - Вплив на якість: залежить від завдання, потребує оцінки - Найкраще для: застосунків з довгим контекстом та обмеженою пам'яттю
Вибір квантизації
| Точність | Економія пам'яті | Вплив на якість | Випадок використання |
|---|---|---|---|
| FP16 | Базовий | Немає | За замовчуванням, критична якість |
| FP8 | 50% | Мінімальний | Продакшн-інференс |
| INT8 | 50% | Низький | Економічні розгортання |
| INT4 | 75% | Помірний | Екстремальні обмеження пам'яті |
Стратегії витіснення кешу
Коли тиск на пам'ять перевищує доступну ємність, політики витіснення кешу визначають, які токени видалити:
Увага з ковзним вікном
Зберігати лише останні токени в кеші, видаляючи старіший контекст:
# Концептуальне ковзне вікно
def sliding_window_cache(kv_cache, window_size):
if len(kv_cache) > window_size:
kv_cache = kv_cache[-window_size:]
return kv_cache
Простий, але ефективний підхід для застосунків, де нещодавній контекст найважливіший. Архітектурне ковзне вікно (як у Mistral) реалізує це нативно.
Витіснення на основі уваги
Видаляти токени з найнижчими оцінками уваги, зберігаючи важливий контекст:
PagedEviction (2025): Алгоритм поблочного витіснення, адаптований для PagedAttention, що ідентифікує та видаляє блоки з низькою важливістю без модифікації CUDA-ядер.⁸
Кешування з керуванням ентропією: Розподіл бюджету кешу на основі ентропії уваги шарів — шари з ширшими патернами уваги отримують більше кешу, фокусовані шари — менше.⁹
Streaming LLM
Для генерації необмеженої довжини Streaming LLM зберігає: - Початкові токени «поглинача уваги» (перші 4-8 токенів) - Останні токени в межах ковзного вікна - Видаляє середній контекст
Цей підхід дозволяє теоретично необмежену генерацію з фіксованою пам'яттю, хоча якість погіршується для завдань, що вимагають залежностей на великій відстані.
Вивантаження KV-кешу
Коли пам'яті GPU недостатньо, вивантажуйте кеш на повільніші рівні зберігання:
Вивантаження на CPU
Переміщення неактивних кешів послідовностей у системну RAM:
# Інтеграція LMCache для вивантаження
from lmcache import LMCacheEngine
cache_engine = LMCacheEngine(
backend="cpu",
max_gpu_cache_size="20GB",
cpu_cache_size="100GB",
)
Вплив на затримку: Передача CPU-GPU додає 10-50 мс на кожне отримання з кешу. Підходить для пакетних навантажень або коли обмеження пам'яті GPU взагалі унеможливлюють обслуговування.
Продуктивність: LMCache з vLLM забезпечує 3-10-кратне зменшення затримки порівняно з повторним обчисленням завдяки кешуванню в пам'яті CPU замість повторної генерації.¹⁰
Вивантаження на диск
Для екстремальних випадків — кешування на NVMe-сховище: - Затримка: 100-500 мс на отримання - Випадок використання: дуже довгі контексти, які інакше були б неможливі - Не підходить для інтерактивних застосунків
Багаторівневе кешування
Продакшн-системи часто реалізують багаторівневе кешування:
- GPU HBM: Гарячі послідовності, що активно генеруються
- CPU RAM: Теплі послідовності, нещодавно активні
- NVMe SSD: Холодні послідовності для потенційного повторного використання
Інтелектуальні політики просування та пониження переміщують кеш між рівнями на основі патернів доступу.
Маршрутизація з урахуванням KV-кешу
Розподілений інференс виграє від маршрутизації запитів до подів, що містять відповідний кеш:
Фреймворк llm-d
Kubernetes-нативний фреймворк з маршрутизацією з урахуванням KV-кешу:¹¹
# Конфігурація маршрутизації кешу llm-d
routing:
strategy: kv_cache_aware
cache_hit_weight: 0.8
load_balance_weight: 0.2
Результати продуктивності: - 87% коефіцієнт влучень у кеш для навантажень з префіксами - На 88% швидший час до першого токена для влучень у теплий кеш - Значне зменшення надлишкових обчислень по кластеру
Патерни реалізації
Липкі сесії: Маршрутизація запитів з однієї розмови до одного поду.
Хешування префіксів: Хешування системних промптів для визначення маршрутизації до поду, забезпечуючи влучення в кеш префіксів.
Маршрутизація з урахуванням навантаження: Балансування локальності кешу та утилізації поду для запобігання гарячим точкам.
Керівництво з планування ємності для продакшну
Оцінка пам'яті
Розрахуйте вимоги до KV-кешу перед розгортанням:
def estimate_kv_cache_memory(
num_layers: int,
hidden_dim: int,
num_kv_heads: int,
head_dim: int,
max_seq_len: int,
max_batch_size: int,
precision_bytes: int = 2, # FP16
) -> float:
"""Оцінка пам'яті KV-кешу в ГБ"""
per_token = num_layers * 2 * num_kv_heads * head_dim * precision_bytes
total = per_token * max_seq_len * max_batch_size
return total / (1024 ** 3)
# Приклад Llama 3.1-70B
memory_gb = estimate_kv_cache_memory(
num_layers=80,
hidden_dim=8192,
num_kv_heads=8, # GQA
head_dim=128,
max_seq_len=8192,
max_batch_size=32,
)
print(f"Пам'ять KV-кешу: {memory_gb:.1f} ГБ")
Планування ємності
Емпіричне правило: Резервуйте 40-60% пам'яті GPU для KV-кешу, решту — для ваг моделі та активацій.
Приклад H100 80 ГБ: - Ваги моделі (70B FP16): ~140 ГБ → 2x GPU з тензорним паралелізмом - Доступно на GPU для кешу: ~30-35 ГБ після ваг та накладних витрат - Максимум одночасних послідовностей: залежить від середньої довжини контексту
Пріоритет оптимізації
- Увімкніть PagedAttention: За замовчуванням у vLLM, значний приріст ефективності
- Увімкніть кешування префіксів: Якщо навантаження мають спільні префікси
- Реалізуйте FP8 KV-кеш: При використанні GPU Hopper/Blackwell
- Додайте маршрутизацію з урахуванням кешу: У масштабі кластера з розподіленим інференсом
- Розгляньте вивантаження: Лише коли пам'яті GPU недостатньо
Моніторинг та спостережуваність
Відстежуйте метрики KV-кешу в продакшні:
Ключові метрики: - Утилізація кешу: відсоток використання виділеного кешу - Коефіцієнт влучень у кеш: ефективність кешу префіксів - Частота витіснень: частота переповнення кешу - Фрагментація пам'яті: втрачений простір у виділених блоках
Ендпоінт метрик vLLM:
# Метрики Prometheus доступні за /metrics
# kv_cache_usage_percent
# kv_cache_total_blocks
# kv_cache_used_blocks
# prefix_cache_hit_rate
Порогові значення для сповіщень: - Утилізація кешу > 90%: масштабуйте ємність або зменшіть розмір батчу - Коефіцієнт влучень < 50%: перегляньте конфігурацію кешування префіксів - Висока частота витіснень: збільшіть виділення пам'яті або оптимізуйте промпти
Організації, що розгортають продакшн LLM-інференс, можуть скористатися інфраструктурною експертизою Introl для планування ємності GPU та оптимізації глобальних розгортань.
Імператив ефективності пам'яті
Оптимізація KV-кешу є одним з найбільш впливових покращень для продакшн-розгортань LLM. Лише PagedAttention забезпечує 2-4-кратне підвищення пропускної здатності — еквівалент подвоєння або почетверення інвестицій у GPU без додаткових витрат на обладнання.
Ландшафт оптимізації продовжує розвиватися. FastGen від Microsoft продемонстрував 50% зменшення пам'яті завдяки адаптивному стисненню. Кешування з керуванням ентропією інтелектуально розподіляє бюджет між шарами. Маршрутизація з урахуванням кешу дозволяє досягти приросту ефективності на рівні кластера, раніше неможливого.
Для організацій, що виконують інференс у масштабі, оптимізація KV-кешу має бути серед перших оцінюваних оптимізацій. Техніки вимагають міні