Затраты, оплата и эксплуатация23 октября 2026 г.Flatkey Team

Выгрузка и многоуровневое хранение KV-кэша для обслуживания LLM с длинным контекстом

Руководство по выгрузке и многоуровневому хранению KV-кэша для обслуживания LLM с длинным контекстом с vLLM и TensorRT-LLM.

Выгрузка и многоуровневое хранение KV-кэша для обслуживания LLM с длинным контекстом

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

Цель не в том, чтобы медленное хранилище выглядело как HBM. Цель — зарезервировать дорогостоящую ёмкость GPU для KV-кэша под активный рабочий набор, сохраняя при этом ценные префиксы доступными в другом месте. Это делает выгрузку KV-кэша наиболее полезной, когда ваш трафик содержит длинные контексты и значимое повторное использование: повторяющиеся системные промпты, каркасы RAG, многоходовые сессии или повторяющиеся префиксы документов.

В этом руководстве показано, как определить, подходит ли многоуровневое хранение, как связаны текущие настройки vLLM, что TensorRT-LLM предоставляет для выгрузки в память хоста и как протестировать изменение, не заменив ошибку нехватки памяти GPU инцидентом с задержкой на хвосте распределения.

Краткий ответ

Используйте выгрузку KV-кэша как контролируемое расширение повторного использования префиксов, а не как стандартное решение проблемы памяти.

Паттерн трафика Начните с Почему
Повторяющиеся длинные системные промпты или префиксы RAG Кэширование префиксов на GPU, затем пилотная выгрузка на CPU Последующий запрос может повторно использовать кэшированный префикс вместо его пересчёта.
Долгоживущие интерактивные сессии с периодами неактивности Тёплый уровень GPU + CPU Неактивный контекст может освободить память GPU, оставаясь при этом доступным для восстановления.
Преимущественно одноразовые уникальные промпты Сначала ёмкость GPU и контроль допуска Блок кэша без будущего повторного использования при выгрузке лишь добавляет работу по передаче данных.
Ограниченная память GPU, но доступна оперативная память хоста Небольшой эксперимент с выгрузкой на CPU Выгрузка может освободить место для активных блоков KV, но стоимость возврата должна укладываться в SLO.
Требуется долговечный нижний уровень Основной уровень CPU плюс протестированный вторичный уровень Вторичный уровень может продлить срок хранения, но не заменяет быстрый активный уровень.

Важное ограничение — локальность. Когда выгруженный блок используется повторно, он должен вернуться в память GPU до того, как механизм внимания начнёт его использовать. Этот путь передачи является частью бюджета задержки запроса.

Что фактически хранит уровень KV-кэша

Во время авторегрессионной генерации слои внимания создают тензоры ключей и значений для обработанных токенов. Сохранение этих тензоров позволяет серверу избежать пересчёта уже обработанного префикса на последующем шаге декодирования или при совместимом повторном использовании префикса. В TensorRT-LLM KV-кэш представлен пулами блоков, хранящих состояние для фиксированного числа токенов; в его документации также описываются повторное использование между запросами, приоритетное удержание и выгрузка в память хоста. Система KV-кэша TensorRT-LLM

Практический стек обслуживания обычно имеет три возможные температурные категории хранения:

Уровень Типичная роль Преимущество Стоимость
GPU HBM Горячее активное состояние prefill и декодирования Минимальная задержка доступа Наименьшая и наиболее дорогая ёмкость
CPU DRAM Тёплые повторно используемые блоки Значительно большая ёмкость; может выступать первой целью выгрузки Возврат на GPU добавляет время передачи
Файловая система или объектный уровень Холодные сохранённые блоки Долговечная или совместно используемая ёмкость Наибольшая стоимость извлечения и больше операционных режимов отказа

Руководство vLLM по выгрузке явно указывает порядок: в его многоуровневой архитектуре CPU используется как основной уровень, а передача между GPU и вторичным уровнем выполняется через этот уровень CPU. Иными словами, попадание в холодный уровень — это не прямое чтение GPU. Руководство по использованию выгрузки KV в vLLM

              возврат при пригодном попадании в кэш
Запрос ──> GPU HBM  <──────────────────── CPU DRAM
              │                                ▲
              │ вытеснение завершённых,         │ промежуточная
              │ повторно используемых           │ передача
              ▼                                │
          активный кэш GPU ─────────────> вторичное хранилище
                 горячий                 тёплый / холодный

Эта диаграмма выгрузки KV-кэша vllm намеренно упрощена: только уровень GPU должен постоянно находиться на критическом пути вычислений. Уровни CPU и хранилища должны обслуживать измеримую политику повторного использования.

Выгрузка KV-кэша — не выгрузка весов модели

Это различие предотвращает удивительно распространённую ошибку конфигурации:

  • Выгрузка KV-кэша перемещает состояние внимания, созданное запросами. Она в первую очередь изменяет объём памяти, доступной для активного контекста, и путь повторного использования.
  • Выгрузка весов модели перемещает параметры модели. В vLLM параметр --cpu-offload-gb документирован в разделе выгрузки весов модели и может добавлять работу по передаче между CPU и GPU к каждому прямому проходу модели. Аргументы vLLM serve

Не предполагайте, что настройка, позволяющая загрузить модель, также создаёт больше пригодной для использования ёмкости KV. Сначала разделите бюджет весов модели, рабочее пространство времени выполнения и бюджет KV-кэша; затем решите, стоит ли сохранять неактивные блоки KV за пределами памяти GPU.

Выгрузка KV-кэша vLLM: начните со встроенного пути через CPU

В текущем CLI vLLM соответствующий флаг выгрузки KV-кэша vllm — --kv-offloading-size. В официальном справочнике CLI указано, что это размер буфера выгрузки KV-кэша в GiB; если тензорный параллелизм больше единицы, размер является суммарным для рангов тензорного параллелизма. Если параметр не задан, выгрузка отключена. Сопутствующий параметр --kv-offloading-backend поддерживает встроенный CPU-бэкенд и LMCache. аргументы vLLM serve

Используйте ограниченный пилотный запуск, а не выделяйте хостовому уровню всю доступную RAM:

vllm serve <your-model> \
  --gpu-memory-utilization 0.85 \
  --kv-offloading-size 16 \
  --kv-offloading-backend native

Этот пример — схема эксперимента, а не универсальная настройка. Подходящее значение зависит от структуры кэша модели, длины контекста, конфигурации тензорного параллелизма, запаса RAM хоста, состава запросов и целевых показателей задержки. Зафиксируйте версию образа vLLM и выполните vllm serve --help в этом образе, прежде чем использовать флаги в production: конфигурация обслуживания быстро развивается.

Встроенный путь подходит для первого испытания выгрузки KV-кэша vllm на CPU, поскольку сужает вопрос многоуровневого хранения: может ли тёплый CPU-уровень сохранить достаточно полезных блоков, чтобы улучшить допуск запросов или избежать вытеснения GPU-кэша, не ухудшая показатели p95 и p99?

Выберите правила добавления в кэш до определения его ёмкости

Большее количество сохранённых блоков не обязательно означает больше полезных блоков. Прежде чем увеличивать буфер выгрузки, ответьте на четыре вопроса:

  1. Какие префиксы являются общими для разных запросов?
  2. Как долго после создания эти префиксы используются повторно?
  3. Каков размер полезного блока относительно вашего бюджета передачи данных хоста?
  4. Какие блоки следует сразу вытеснять, поскольку вероятность их повторного использования слишком мала?

Если по трассировкам рабочей нагрузки невозможно ответить на первые два вопроса, начните с измерения повторного использования префиксов на GPU. CPU-уровень может сохранять состояние тёплого кэша; он не может создать повторное использование для полностью уникальных промптов.

Создавайте путь многоуровневого хранения vLLM только после пилота на CPU

OffloadingConnector в vLLM — это путь к основному CPU-уровню и необязательным вторичным уровням. В официальном руководстве описываются CPUOffloadingSpec для одного CPU-уровня и TieringOffloadingSpec для основного CPU-уровня с одним или несколькими вторичными уровнями. В нём также указаны LRU и ARC как встроенные варианты политик вытеснения. руководство по использованию выгрузки KV в vLLM

Ниже приведена точная схема конфигурации из документированного примера с несколькими уровнями. Заменяйте модель, пути, размер блока, объём в байтах и число потоков только после их тестирования на собственном хосте:

vllm serve <your-model> \
  --kv-transfer-config '{
    "kv_connector": "OffloadingConnector",
    "kv_role": "kv_both",
    "kv_connector_extra_config": {
      "spec_name": "TieringOffloadingSpec",
      "cpu_bytes_to_use": 10737418240,
      "block_size": 16,
      "eviction_policy": "lru",
      "secondary_tiers": [
        {
          "type": "fs",
          "root_dir": "/mnt/kv_cache",
          "n_read_threads": 32,
          "n_write_threads": 16
        }
      ]
    }
  }'

Три эксплуатационных детали важнее простого копирования фрагмента:

  1. cpu_bytes_to_use — это суммарный резерв для CPU-уровня по всем воркерам, а не расплывчатая рекомендация операционной системе. Учтите бюджет процесса, ОС, страничного кэша хранилища и всех совместно размещённых сервисов.
  2. Настроенный размер блока или чанка определяет единицу ввода-вывода. Очень маленькие чанки могут увеличить накладные расходы на метаданные и планирование; очень большие — перемещать байты, не нужные запросу. Протестируйте оба варианта на реальных длинах префиксов.
  3. Вторичный уровень располагается после CPU. Если CPU-уровень слишком мал или перегружен, добавление ёмкости файловой системы может сохранить больше данных, но не улучшить задержку последующего попадания в кэш.

Таким образом, цель выгрузки KV-кэша vllm — не «сохранять всё». Она состоит в том, чтобы «сохранять блоки с реалистичным и своевременным путём повторного использования».

Выгрузка KV-кэша TensorRT-LLM в память хоста

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

При внедрении выгрузки KV-кэша tensorrt-llm в память хоста обращайте внимание не только на ёмкость, но и на политику удержания:

Элемент управления TensorRT-LLM Что проверить
host_cache_size Бюджет в байтах задан осознанно и оставляет запас памяти хоста.
Приоритет блока / политика удержания Часто повторно используемые области промпта сохраняются раньше данных, которые можно удалить.
secondary_offload_min_priority Низкоприоритетные блоки могут обходить выгрузку на хост и вытесняться напрямую, уменьшая избегаемый трафик хоста.
Повторное использование блоков между запросами Повторное использование остаётся включённым и наблюдаемым отдельно от оценок планировщика.

На момент написания документация TensorRT-LLM указывает значение по умолчанию secondary_offload_min_priority, равное 35. Рассматривайте его как зависящее от версии значение по умолчанию, а не как рекомендацию по политике: порог должен отражать наблюдаемую ценность повторного использования и стоимость передачи данных для вашего сервиса.

Метод внедрения, защищающий задержку

Не включайте холодный уровень во время инцидента с нехваткой ёмкости и не объявляйте успех, когда прекращаются OOM-ошибки. Вместо этого выполните контролируемую последовательность действий:

  1. Зафиксируйте базовый уровень только с GPU. Запишите распределение длины контекста, конкурентность, время до первого токена, межтокенную задержку, сквозные p50/p95/p99, долю повторного использования префиксов и поведение вытеснения KV-кэша на GPU.
  2. Зарезервируйте реальный запас памяти хоста. Учитывайте накладные расходы среды выполнения и операционную систему; не определяйте размер CPU-кэша только по снимкам свободной памяти.
  3. Включите небольшой уровень CPU. Сохраняйте неизменными модель, политику батчинга, профиль трафика и SLO-оповещения, меняя только одно измерение кэша.
  4. Сравнивайте качество попаданий, а не только их количество. Разделяйте попадания в GPU, перемещения в GPU из CPU, перемещения из холодного уровня и промахи, запускающие повторные вычисления.
  5. Анализируйте хвостовую задержку при конкуренции за ресурсы. Запускайте смешанные длинные и короткие запросы, а также наращивайте конкурентность. Результат, основанный только на среднем значении, скрывает очереди передачи данных.
  6. Добавляйте вторичный уровень только если это оправдано ценностью хранения. Перед широким внедрением протестируйте потерю кэша, давление на хранилище, поведение при перезапуске и всплески перемещений.
  7. Задайте правило отката. Например: отключайте самый новый уровень, если p99 времени до первого токена или межтокенной задержки превышает согласованный бюджет в течение длительного интервала.

Руководство vLLM описывает метрики конфигурации и выгрузки, включая сведения о конфигурации и сигналы использования CPU-кэша. Используйте их вместе с трассировками приложения: метрика кэша без задержки на уровне запроса затрудняет различение ценного перемещения и неэффективных передач данных. Руководство по использованию выгрузки KV в vLLM

Сбои, которые следует предотвратить на этапе проектирования

Режим сбоя Как это выглядит Лучший ответ
Считать все блоки кэша ценными Уровень CPU заполняется, число перемещений растёт, задержка ухудшается Добавляйте в кэш и сохраняйте на основе признаков повторного использования, а не только порядка создания.
Путать выгрузку весов с выгрузкой KV-кэша Модель загружается, но конкурентность при длинном контексте остаётся низкой Разделяйте бюджеты для весов, KV, рабочего пространства и запаса безопасности.
Чрезмерно выделять RAM хоста Хост начинает высвобождать память либо совместно размещённые сервисы становятся нестабильными Резервируйте фиксированный бюджет и проводите нагрузочное тестирование в условиях реалистичной конкуренции.
Слишком рано добавлять вторичный уровень Больше сохранённых байтов, но нет значимого улучшения SLO Сначала подтвердите повторное использование на уровне CPU, затем отдельно протестируйте холодный уровень.
Игнорировать топологию передачи данных Хороший лабораторный результат, плохой p99 на совместно используемом узле Проводите бенчмарки на точно такой же топологии GPU, CPU, PCIe/NVLink и пути к хранилищу, которая используется в продакшене.
Скрывать поведение кэша от операторов Инцидент выглядит как случайная вариативность задержки Предоставляйте сигналы по уровням: попадания, перемещения, вытеснения, ёмкость и ошибки.

Когда выгрузка KV-кэша — неподходящая оптимизация

Пока не используйте выгрузку KV-кэша, если:

  • Память GPU не является ограничивающим фактором.
  • Почти все промпты уникальны, поэтому сохранённые префиксы не используются повторно.
  • Ваш основной SLO — очень низкая хвостовая задержка, и невозможно подтвердить, что путь передачи данных укладывается в него.
  • DRAM хоста или хранилище уже являются дефицитными производственными ресурсами.
  • Кэширование префиксов, батчинг, ограничения контекста, выбор модели или квантизация кэша ещё не оценивались.

В этих случаях более разумным первым шагом может быть пересмотр бюджета памяти GPU, другая политика контекста или изменение архитектуры обслуживания. Сведения о выборе топологии и параллелизма см. в статьях Мульти-GPU-инференс vLLM, vLLM и SGLang и TensorRT-LLM и vLLM.

Часто задаваемые вопросы

Снижает ли выгрузка KV-кэша использование памяти GPU?

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

Какой флаг vLLM отвечает за выгрузку KV-кэша?

В текущей документации vLLM CLI параметр --kv-offloading-size включает буфер выгрузки KV при заданном значении, а --kv-offloading-backend выбирает бэкенд. Проверьте точные флаги в используемом вами закреплённом релизе vLLM. Аргументы vLLM serve

Является ли уровень файловой системы прямым кэшем GPU?

Нет. В документации vLLM CPU указан как основной уровень его многоуровневой реализации; передача между GPU и вторичным уровнем выполняется через память CPU. Поэтому тесты вторичного уровня должны включать полный путь перемещения.

Лучше ли выгрузка KV-кэша, чем покупка более крупного GPU?

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

Заключение: рассматривайте выгрузку KV-кэша как политику кэширования, а не как способ увеличить ёмкость

Наиболее эффективная архитектура выгрузки KV-кэша хранит активное состояние на GPU, резервирует память CPU для подтверждённого данными повторного использования прогретого кэша и добавляет холодный уровень только тогда, когда хранение остаётся ценным после оценки стоимости передачи и обработки сбоев. Начните с ограниченного пилотного проекта на CPU, инструментируйте повышения между уровнями и задержку по уровням и внедряйте только ту политику, которая улучшает производственный SLO, а не просто объём сохраняемого кэша.

Если операционные расходы на самостоятельно размещаемый стек обслуживания превышают необходимый вашей нагрузке уровень контроля, сравните развёртывание в GPU-облаке с model API или ознакомьтесь с Flatkey Compute, прежде чем переходить к более крупному парку серверов.

Источники