На предыдущую страницу
Блог

KV-кеш: почему при длинном контексте заканчивается память GPU

Контекстные окна языковых моделей выросли до сотен тысяч токенов. Например, у Llama 3.1 это 128 тыс. токенов. Сейчас в один запрос помещаются договор целиком, кодовая база или многочасовая переписка с клиентом. Однако на практике длинному контексту не хватает видеопамяти. Модель загрузилась на GPU и отвечает на короткие вопросы, но на длинном документе сервер выдает ошибку нехватки памяти или начинает обслуживать меньше пользователей.

При длинном контексте значительную часть дополнительной памяти может занимать KV Cache (KV-кеш). Во время инференса он хранит ключи (K) и значения (V) attention для уже обработанных токенов, чтобы модель не пересчитывала их на каждом шаге генерации.

Веса модели занимают относительно фиксированный объем VRAM, а KV-кеш увеличивается вместе с длиной контекста и числом одновременных запросов. Поэтому при длинном контексте он может занять десятки гигабайт видеопамяти, и его объем нужно учитывать вместе с весами модели.

Как работает KV-кеш

Языковая модель генерирует ответ по одному токену. Чтобы сгенерировать следующий токен, механизм внимания (attention) сопоставляет запрос текущего токена с ключами предыдущих токенов контекста. Для этого на каждом слое модели для каждого токена вычисляются два вектора: ключ (key) и значение (value).

Без кеширования модель пересчитывала бы ключи и значения всего контекста на каждом шаге генерации. Для ответа из 500 токенов их пришлось бы заново вычислять для всей уже обработанной последовательности. KV-кеш сохраняет рассчитанные векторы в видеопамяти. На каждом шаге модель считает их только для нового токена и использует данные из кеша для предыдущих.

Поэтому работа модели делится на две фазы.

Предзаполнение (prefill) — модель обрабатывает весь входной контекст за один проход и заполняет KV-кеш. Эта фаза нагружает вычислительные блоки GPU и определяет время до первого токена.

Генерация (decode) — модель выдает ответ токен за токеном. На каждом шаге она читает из памяти веса и весь накопленный KV-кеш. Эта фаза ограничена пропускной способностью памяти.

Кеш снижает объем вычислений за счет памяти. Чем длиннее контекст, тем больше памяти он занимает.

Сколько памяти занимает KV-кеш

Объем кеша на один токен считается по формуле:

2 × число слоев × число KV-голов × размерность головы × байт на значение

Множитель 2 — это два вектора, ключ и значение. Чтобы получить объем для запроса, результат умножают на длину контекста в токенах. Чтобы получить объем для сервера, его умножают еще и на число одновременных запросов.

Пример: Llama 3.1 70B. У модели 80 слоев, 8 KV-голов и размерность головы 128. В 16-битном формате каждое значение занимает 2 байта.

2 × 80 × 8 × 128 × 2 = 327 680 байт, то есть около 328 КБ на один токен.
Длина контекста KV-кеш на один запрос (FP16) KV-кеш на один запрос (FP8)
8 тыс. токенов 2,7 ГБ 1,3 ГБ
32 тыс. токенов 10,7 ГБ 5,4 ГБ
128 тыс. токенов 43 ГБ 21,5 ГБ

Веса этой модели занимают около 140 ГБ в 16-битном формате и около 70 ГБ в 8-битном. Пусть модель с 8-битными весами работает на одном GPU со 141 ГБ памяти, а кеш остается 16-битным. После загрузки весов свободно около 70 ГБ: это примерно два десятка диалогов по 8 тыс. токенов с запасом на служебные расходы. Запрос на 128 тыс. токенов занимает 43 ГБ, и таких запросов сервер обслужит только один.

Число KV-голов напрямую влияет на объем KV-кеша. В Llama 3.1 70B используется grouped-query attention (GQA): 64 головы внимания делят между собой 8 наборов ключей и значений. Без GQA каждая голова хранила бы свои векторы, и кеш был бы в 8 раз больше. Один запрос на 128 тыс. токенов занял бы около 340 ГБ, больше памяти любого отдельного GPU.

Почему память заканчивается раньше расчета

Формула дает нижнюю границу. В реальной работе памяти требуется больше по двум причинам.

Служебные расходы. Кроме весов и кеша, в памяти лежат промежуточные активации, буферы фреймворка и библиотек. Движки инференса обычно резервируют часть памяти заранее.
Фрагментация. Системы инференса выделяли под каждый запрос непрерывный блок памяти на максимально возможную длину последовательности. Реальный ответ почти всегда короче, и зарезервированная память простаивала. По оценке разработчиков vLLM, в 2023 году такие системы теряли 60–80% памяти, отведенной под KV-кеш.

Последствия видны пользователю. Сервер либо отказывает в запросе с длинным контекстом, либо движок сокращает число одновременно обрабатываемых запросов. Во втором случае растет очередь, а стоимость одного запроса увеличивается: тот же GPU обслуживает меньше пользователей.

Почему длинный контекст замедляет генерацию

На каждом шаге генерации модель читает весь KV-кеш запроса. Чем длиннее контекст, тем больше данных проходит через память на каждый токен ответа. Даже если кеш целиком поместился в видеопамять, на длинном контексте токены выдаются реже: скорость ограничена пропускной способностью памяти, а не вычислениями.

Как сократить KV-кеш

Кеш сокращают на разных уровнях, от выбора модели до настроек движка инференса. Способы складываются.

Модель с эффективной архитектурой внимания. GQA и multi-query attention (MQA) уменьшают число хранимых наборов ключей и значений. В MQA все головы делят один набор. Есть еще два механизма. Первый — сжатие ключей и значений в компактное скрытое представление (MLA в моделях DeepSeek). Второй — окно внимания фиксированной длины: модель хранит кеш только последних N токенов. Архитектура задается при обучении, поэтому для арендатора это решение на этапе выбора модели: у двух моделей одного размера объем кеша на токен может различаться в разы. Перед выбором стоит проверить в конфигурации модели число слоев и KV-голов.
Квантование KV-кеша. Ключи и значения хранятся в 8 или 4 битах вместо 16. Переход на FP8 вдвое сокращает объем кеша. На GPU архитектуры Blackwell доступен формат NVFP4: он сокращает объем кеша еще вдвое по сравнению с FP8. По данным NVIDIA, потери точности при этом меньше 1% на тестах генерации кода, знаний и длинного контекста. Потери зависят от модели и задачи, поэтому результат проверяют на своих запросах.
Страничное управление памятью. Метод PagedAttention, лежащий в основе vLLM, делит кеш на небольшие блоки и выделяет их по мере роста ответа, как операционная система выделяет страницы памяти. По данным разработчиков, потери памяти при этом меньше 4%.
Кеширование префикса (prefix caching). Системный промпт, инструкции и общий документ часто повторяются от запроса к запросу. Движок сохраняет KV-кеш этой части и не вычисляет его заново. Это сокращает время до первого токена и экономит вычисления в фазе предзаполнения.
Выгрузка кеша в память CPU и на диск. Неактивные части кеша переносятся из видеопамяти в оперативную память сервера или на быстрые накопители. Когда пользователь возвращается к диалогу, кеш подгружается обратно без повторного вычисления. Такую схему поддерживает, например, фреймворк NVIDIA Dynamo: в тесте с GPUDirect Storage подгрузка шла со скоростью 35 ГБ/с на один H100. На медленном канале выигрыша нет, пересчет предзаполнения может оказаться быстрее подгрузки.
Ограничение контекста под задачу. Многим сценариям не нужны сотни тысяч токенов. Поиск по базе знаний (RAG) передает модели только релевантные фрагменты документов. Чем короче контекст, тем меньше кеш и тем больше пользователей обслуживает один GPU.

Кейс Character.AI: кеш уменьшили в 20 раз

Компания Character.AI, сервис диалогов с ИИ-персонажами, описала свою оптимизацию инференса. Ее модели обрабатывают длинные многоходовые диалоги, и KV-кеш стал главным ограничением.

Команда объединила несколько методов. Multi-query attention сократила объем KV-кеша в 8 раз. Дополнительно использовались ограниченные горизонты внимания и совместное использование KV-кеша между слоями, которое дало еще 2–3 раза. По оценке Character.AI, сочетание этих архитектурных методов уменьшило KV-кеш более чем в 20 раз без снижения качества. Отдельно компания использует int8 для весов, активаций и KV-кеша.

Второй шаг касался повторного использования. Кеш диалога сохраняется между репликами пользователя, и при следующей реплике его не нужно вычислять заново. Доля попаданий в кеш достигла 95%. По данным компании, стоимость обслуживания запросов снизилась в 33 раза по сравнению с концом 2022 года.

Архитектурные способы сокращения KV-кеша задаются при разработке и обучении модели. При работе с готовой моделью можно использовать квантование KV-кеша, страничное управление памятью и кеширование префикса. Итоговый объем кеша зависит от архитектуры модели, формата хранения ключей и значений и настроек движка инференса.

Как выбрать GPU под длинный контекст

Для задач с длинным контекстом важны два параметра GPU. Объем видеопамяти определяет, сколько контекста и сколько одновременных запросов поместится. Пропускная способность памяти влияет на скорость генерации на длинном контексте.

GPU Видеопамять Пропускная способность Для каких задач
NVIDIA RTX PRO 6000 Blackwell Server Edition 96 ГБ GDDR7 1,6 ТБ/с Модели от 40 млрд параметров с длинным контекстом
NVIDIA H100 (SXM) 80 ГБ HBM3 3,35 ТБ/с Инференс средних и крупных моделей, высокая нагрузка
NVIDIA H200 141 ГБ HBM3e 4,8 ТБ/с Крупные модели с длинным контекстом и много одновременных пользователей

Если модель и кеш не помещаются в один GPU, их распределяют между несколькими ускорителями на одном сервере. При тензорном параллелизме каждый GPU хранит свою часть весов и кеша, а на каждом шаге генерации карты обмениваются промежуточными результатами. Скорость обмена задает канал между картами: NVLink там, где он есть, иначе PCIe. У RTX PRO 6000 NVLink нет, и это стоит учитывать при сборке из нескольких карт под одну модель.

Расчет под конкретную задачу идет по шагам:

• определить модель и формат весов;
• посчитать по формуле кеш для типичной и максимальной длины контекста;
• умножить на ожидаемое число одновременных запросов;
• добавить запас на служебные расходы.

Такой расчет показывает, помещается ли нагрузка на один GPU или модель и KV-кеш придется распределять между несколькими ускорителями.

GPU-инфраструктура ITGLOBAL.COM

Основа инфраструктуры ITGLOBAL.COM — ускорители NVIDIA: H200 и RTX PRO 6000 Blackwell Server Edition. H200 со 141 ГБ памяти подходит для крупных моделей с длинным контекстом, RTX PRO 6000 с 96 ГБ — для моделей среднего размера. Для проектов, где нужна альтернатива NVIDIA, доступен ИИ-ускоритель SOPHGO SC7 HP75-2. Мощности предоставляются в нескольких форматах.

Облачные серверы с GPU — виртуальные машины с ускорителями. GPU отдается целиком через PCIe Passthrough или делится между машинами через NVIDIA vGPU. Облачный вариант удобен для пилота, когда нужно проверить реальное потребление памяти до выбора постоянной конфигурации.
Выделенные серверы с GPU (Dedicated GPU) — физический сервер целиком для одного клиента, до восьми ускорителей. Такой сервер используют при стабильной высокой нагрузке и для конфигураций с несколькими GPU.
Инференс нейросетей в облаке — запуск готовой модели на мощностях ITGLOBAL.COM. Здесь готовая модель доступна как сервис, без самостоятельного администрирования GPU-сервера.
AI Cloud — набор корпоративных ИИ-сервисов. Подходит для задач, где данные и ИИ-сервисы должны работать в одном облачном контуре.
AIaaS — единый API-шлюз к российским и зарубежным языковым моделям, без собственных GPU. Формат подходит, когда длинный контекст нужен эпизодически и держать под него оборудование невыгодно.

Для обучения крупных моделей доступна аренда суперкомпьютера на базе NVIDIA SuperPOD.

Серверы размещаются в дата-центрах 7 стран, в том числе в Москве, Минске, Алматы, Ташкенте и Дубае.

Специалисты ITGLOBAL.COM помогут рассчитать объем памяти под вашу модель, длину контекста и число пользователей и подобрать конфигурацию GPU, на которой длинному контексту хватит видеопамяти.

Что учитывать при расчете памяти

При расчете GPU под длинный контекст нужно учитывать память под веса модели, KV-кеш и служебные данные движка. Объем кеша считают для рабочей длины контекста и ожидаемого числа одновременных запросов. Если доступной VRAM не хватает, проверяют квантование и управление кешем, сокращают контекст или распределяют нагрузку между несколькими GPU.

Частые вопросы

KV Cache — это кеш ключей (K) и значений (V), рассчитанных для уже обработанных токенов. Модель использует их повторно при генерации следующих токенов, чтобы не вычислять эти данные заново для всей предыдущей последовательности.
При запуске модели основную часть видеопамяти могут занимать ее веса и служебные данные. KV-кеш растет по мере обработки контекста. На коротких запросах памяти хватает, на длинном документе кеш занимает оставшийся объем, и сервер выдает ошибку нехватки памяти.
Можно, и это самый прямой путь. Но объем кеша растет линейно с длиной контекста и числом пользователей. Квантование кеша и страничное управление памятью часто дают тот же эффект без смены оборудования.
Для FP8 потери обычно минимальны. Для 4-битных форматов результат зависит от модели и задачи. Перед запуском качество проверяют на собственных запросах с реальной длиной контекста.
Кеширование промптов — это и есть кеширование префикса, только со стороны провайдера модели. Внутри одного запроса KV-кеш живет на время генерации. Кеширование префикса сохраняет кеш повторяющейся части запроса и переиспользует его в следующих запросах, поэтому провайдеры тарифицируют такие токены дешевле.
Посчитать кеш на токен по конфигурации модели, умножить на длину контекста и число одновременных запросов, добавить веса модели и запас на служебные расходы.
Оцените данную статью

Узнавайте о выходе новых статей в блоге первыми!

Подпишитесь на нашу рассылку