LLM-инференс в продакшене — Часть 2: Квантование и KV-кэш
опубликовано: ⏰ 31В Части 1 рассматривались архитектуры моделей и ключевые метрики инференса в продакшене. Это Часть 2 из 4 – она посвящена двум крупнейшим потребителям VRAM: весам модели и KV-кэшу. Мы рассмотрим, как квантование уменьшает веса модели, и как методы работы с KV-кэшем освобождают память для увеличения размеров батчей.
Часть 1: Архитектура и метрики ← Часть 2: Квантование и KV-кэш → Часть 3: Параллелизм и скорость → Часть 4: Фреймворки и операции
Квантование
Что такое квантование
Квантование снижает числовую точность весов и активаций модели. Модель, обученная в FP32, использует 32 бита на число. Квантование отображает эти значения на меньшее количество бит, обычно FP16, BF16, FP8, INT8, INT4 или, все чаще, INT2. Компромисс всегда одинаков: меньше бит на параметр означает меньший объем памяти и более быстрые вычисления ценой некоторой потери точности представления.
Почему это важно? Большие языковые модели ограничены тремя ресурсами: объемом VRAM, пропускной способностью памяти и вычислительной пропускной способностью. Квантование затрагивает все три аспекта одновременно. Уменьшение разрядности бит вдвое вдвое снижает объем занимаемой памяти, удваивает эффективную пропускную способность и часто позволяет оборудованию обрабатывать больше элементов за цикл. Для модели на 70 млрд параметров переход с FP16 на INT4 может снизить потребность в VRAM примерно на 75%, превращая требование в 140 ГБ примерно в 35 ГБ.
Квантование работает на разных уровнях детализации (granularity). Потензорное квантование (Per-tensor) использует единый масштаб и нулевую точку для всего тензора. Поканальное квантование (Per-channel) назначает один масштаб на выходной канал, сохраняя больше деталей для каналов с выбросами. Погрупповое квантование (Per-group) разбивает каждый канал на небольшие группы, обычно по 32 или 64 элемента, квантуя каждую группу независимо. Потокенное квантование (Per-token) применяет масштабы на уровне детализации оценки внимания (attention-scoring), часто для сжатия KV-кэша. Более мелкая детализация лучше сохраняет точность, но добавляет накладные расходы на отслеживание метаданных масштабирования.
FP8: Стандарт для дата-центров
К 2026 году FP8 зарекомендовал себя как точность по умолчанию для инференса LLM в дата-центрах на GPU H100, H200 и B200. FP8 поставляется в двух форматах: E4M3 (4-битная экспонента, 3-битная мантисса) для весов и активаций, и E5M2 (5-битная экспонента, 2-битная мантисса) для градиентов во время обучения. Формат E4M3 обеспечивает достаточный динамический диапазон для распределений весов, помещаясь в нативные FP8 Tensor Cores.
Квантование FP8 обычно требует минимальной калибровки по сравнению с INT4. Большинство моделей можно преобразовать в FP8 с помощью простых потензорных или поканальных коэффициентов масштабирования, вычисленных на небольшом наборе данных для калибровки. Потеря точности часто незначительна – обычно 0,1-0,5% на стандартных бенчмарках – что делает FP8 оптимальной точкой (sweet spot) для продакшен-развертываний, где важны и производительность, и качество.
Архитектура Hopper (H100/H200) поддерживает FP8 с аппаратно-точным масштабированием, обеспечивая истинные вычисления FP8 без накладных расходов на деквантование. Это делает FP8 особенно привлекательным для развертываний со смешанной точностью: веса в FP8, KV-кэш в FP8 и активации, вычисляемые в FP8 с избирательным приведением к FP16 (upcasting) для численно чувствительных операций.
W4A4: Квантование и весов, и активаций
До недавнего времени квантование в продакшене следовало паттерну W4A16: 4-битные веса с активациями, остающимися в FP16. Этот подход упрощал калибровку, поскольку требовался анализ только статических распределений весов. Однако GPU Hopper и последующих архитектур имеют INT4 Tensor Cores, которые требуют, чтобы оба операнда были в INT4 для реализации полного 4-кратного ускорения вычислений.
QuaRot сделал W4A4 жизнеспособным для продакшена. Он применяет матрицы вращения Хадамара (Hadamard) к распределениям весов перед квантованием, устраняя выбросы и равномерно распределяя ошибку квантования по каналам. Результатом являются веса INT4 и активации INT4 с деградацией точности, сопоставимой с W4A16 PTQ, при этом раскрывается полная вычислительная пропускная способность INT4 Tensor Cores. Для развертываний, ограниченных вычислениями (compute-bound) на оборудовании Hopper, W4A4 обеспечивает измеримо более высокую пропускную способность, чем W4A16, при идентичном качестве. Связанная работа — QServe (QoQ) — нацелена на другую конфигурацию: W4A8KV4, используя вращение и сглаживание для весов INT4, активаций INT8 и KV-кэша INT4 одновременно.
PTQ (Квантование после обучения)
Квантование после обучения (Post-Training Quantization) преобразует предварительно обученную модель в более низкую точность без какого-либо градиентного дообучения. Процесс требует небольшого набора данных для калибровки, обычно от 100 до 500 неразмеченных примеров, похожих на ожидаемую область развертывания модели. Шаг калибровки запускает модель в FP16 на этих примерах, собирает статистику активаций и вычисляет оптимальные масштабные коэффициенты для каждого уровня детализации квантования. Калибровка обычно завершается за несколько минут на одном GPU.
GPTQ выполняет послойное квантование с использованием информации второго порядка. Он аппроксимирует матрицу Гессе для каждого слоя весов и использует разложение Холецкого для ее факторизации, а затем квантует столбцы матрицы весов в порядке, минимизирующем распространение ошибки. Стратегия последовательного квантования обрабатывает один набор столбцов за раз, вычисляя матрицу восстановления, которая компенсирует ошибку квантования перед переходом к следующим столбцам. GPTQ быстр, надежен и обеспечивает хорошую точность для целей INT4 и INT3, что делает его одним из самых широко применяемых методов PTQ для квантования до низкого числа бит.
AWQ (Activation-Aware Weight Quantization) улучшает GPTQ за счет изучения распределений активаций во время калибровки. Он определяет “важные” каналы – нейроны с большими амплитудами активаций, которые вносят непропорционально большой вклад в точность модели – и сохраняет их в более высокой точности. Менее важные каналы подвергаются агрессивному квантованию. Этот выборочный подход последовательно достигает лучшей точности, чем GPTQ при той же разрядности бит, обычно сокращая разрыв в 1-2% на бенчмарках вроде MMLU и HELM. AWQ работает на уровнях квантования INT4, INT8 и даже FP8.
SmoothQuant подходит с другой стороны. Он решает проблему, заключающуюся в том, что активации квантовать сложнее, чем веса, поскольку активации имеют распределения с тяжелыми хвостами и экстремальными выбросами. SmoothQuant применяет поканальный сглаживающий коэффициент, который уменьшает масштаб крупных пред-активаций и увеличивает масштаб соответствующих строк весов, перенося сложность квантования с активаций полностью на веса. Поскольку веса статичны и их легче анализировать, это перераспределение позволяет проводить агрессивное квантование активаций без коллапса точности. SmoothQuant особенно эффективен для развертывания INT8 на оборудовании, которое квантует и веса, и активации.
Методы PTQ имеют общие сильные и слабые стороны. Главное преимущество – скорость: не нужна инфраструктура для обучения, кластер GPU и недели экспериментов. Запуск PTQ может занять от нескольких минут до часов. Главный недостаток – потолок точности: PTQ обычно теряет 1-8% точности в зависимости от целевой разрядности бит, и существует жесткий предел, ниже которого модель деградирует недопустимо. Для INT8 и FP8 потеря часто находится в диапазоне 0,5-2% и может быть незначительной для продакшена. Для INT4 потери возрастают до 3-8%, а для INT2 деградация часто является неприемлемой без подхода QAT.
QAT (Обучение с учетом квантования)
Обучение с учетом квантования (Quantization-Aware Training) моделирует арифметику низкой точности во время самого процесса обучения. В отличие от PTQ, который является шагом преобразования постфактум, QAT модифицирует цикл обучения так, что модель учится работать в условиях шума квантования с самого начала. Результатом является модель, структурно адаптированная к выживанию при агрессивном снижении точности.
Основной механизм QAT опирается на два компонента. Во-первых, в граф вычислений в стратегических точках вставляются узлы FakeQuant, обычно до и после операций линейного слоя. Во время прямого прохода эти узлы квантуют значения до целевой точности и немедленно деквантуют обратно в FP32 или FP16, симулируя потерю информации, которую произвела бы реальная целочисленная арифметика. Во время обратного прохода фактических целочисленных градиентов не существует, поэтому QAT использует Straight-Through Estimator (STE) для аппроксимации градиентов. Оператор STE пропускает градиенты напрямую через функцию квантования, обращаясь со ступенчатой границей квантования так, как если бы это была тождественная функция. Эта аппроксимация не является математически строгой, но работает на практике, поскольку предоставляет оптимизатору сигнал, пропорциональный величине значений.
В течение эпох обучения веса и смещения модели смещаются, чтобы учесть шум квантования. Нейроны, чувствительные к потере точности, корректируют свои амплитуды до более удобных для квантования значений. Активации с выбросами распределяют свое влияние по нескольким каналам, а не концентрируются в распределениях с тяжелыми хвостами. Модель фактически учится устойчивости к целочисленной арифметике как свойству своих параметров.
Главное преимущество QAT – точность. При INT4 модель QAT обычно теряет всего 1-3% на стандартных бенчмарках по сравнению с 3-8% для PTQ. При INT2 QAT может достичь деградации в 5-15%, тогда как PTQ часто неработоспособен. Для самых низких разрядностей бит QAT – это не просто улучшение, это единственный жизнеспособный путь.
Недостатки существенны. QAT требует полной инфраструктуры обучения: кластеров GPU, фреймворков распределенного обучения, конвейеров данных и инструментов мониторинга. Время обучения сопоставимо с полным файн-тюнингом, часто от дней до недель в зависимости от размера модели. Недавние разработки несколько сузили этот разрыв. В июне 2026 года Google выпустила чекпойнты Gemma 4 QAT с 4-битным форматом (Q4_0) и мобильным QAT-форматом, использующим избирательное 2-битное сжатие на слоях генерации токенов, продемонстрировав, что QAT может достигать точности продакшен-качества при агрессивных разрядностях бит, когда он применяется оригинальными авторами модели с доступом к обучающим данным и вычислительным мощностям.
Типы квантования GGUF и llama.cpp
GGUF – это универсальный формат сериализации, разработанный вокруг движка инференса llama.cpp. Он хранит веса модели вместе с метаданными квантования, словарем и конфигурацией архитектуры в одном переносимом файле. Поскольку GGUF существует вне экосистемы GPU-фреймворков, он разработал собственные типы квантования, которые отдают приоритет эффективности инференса на CPU.
Наиболее распространенные типы квантования GGUF следуют соглашению об именовании. Q4_0 выполняет базовое 4-битное квантование с погрупповым масштабированием. Это базовый уровень квантования, балансирующий использование памяти и точность. Q4_K_M является частью семейства типов квантования “K”. Типы “K” используют смешанную точность: большинство весов квантуется до 4 бит, но каналы с выбросами – определенные во время квантования – сохраняются в более высокой точности (Q6 или Q8). Суффикс “M” выбирает баланс средней детализации между памятью и точностью. Q5_K_M следует тому же паттерну смешанной точности, но выделяет 5 бит для базовой точности, возвращая точность ценой дополнительной памяти. Q8_0 использует простое 8-битное погрупповое квантование, обеспечивая почти безпотерную точность примерно с половиной объема памяти от FP16.
Типы квантования “K” являются самой значимой инновацией в квантовании GGUF. Анализируя распределения весов и выявляя каналы со значениями, которые значительно отклоняются от среднего по группе, квантователь назначает большую разрядность бит каналам с выбросами, в то же время сжимая большинство каналов более агрессивно. Этот подход признает, что не все веса одинаково важны, и что равномерное квантование тратит биты на легко сжимаемые области, лишая битов сложно сжимаемые.
Квантованные модели GGUF являются выбором по умолчанию для инференса на CPU и периферийного развертывания (edge deployment). Среда выполнения llama.cpp использует эффективное умножение матриц на основе таблиц поиска, которое избегает полного деквантования в FP32, сохраняя арифметику в целочисленном и 8-битном доменах для большей части вычислений. На потребительском оборудовании с 16 ГБ объединенной памяти квантованная модель 13B Q4_K_M работает там, где аналог в FP16 не поместится.
Сравнение форматов квантования
| Формат | Бит | Метод | VRAM (модель 7B) | Ускорение | Потеря точности | Инструменты |
|---|---|---|---|---|---|---|
| FP32 | 32 | Базовый | ~28 GB | 1x | 0% | Нативное |
| FP16/BF16 | 16 | Нативное | ~14 GB | ~2x | ~0% | Стандартное |
| FP8 | 8 | Per-tensor | ~7 GB | ~2x | 0.1-0.5% | TensorRT-LLM, vLLM |
| INT8 PTQ | 8 | AWQ/SmoothQuant | ~7 GB | ~2x | 1-2% | vLLM, TensorRT-LLM |
| INT4 W4A16 PTQ | 4 | GPTQ/AWQ | ~3.5 GB | ~2x | 3-8% | GGUF, vLLM |
| INT4 W4A4 PTQ | 4 | QuaRot | ~3.5 GB | ~8x (вычисления) / 4x (память) | 3-8% | QServe (исследование) |
| INT4 QAT | 4 | QAT | ~3.5 GB | ~4x | 1-3% | TensorRT-LLM, vLLM |
| INT2 QAT | 2 | QAT | ~1.75 GB | ~8x | 5-15% | LiteRT (Gemma 4) |
Цифры VRAM предполагают веса модели плюс умеренный KV-кэш. Фактические требования к памяти увеличиваются с размером батча и длиной контекста, поскольку память активаций и KV-кэша не всегда квантуется. Столбец ускорения отражает теоретический прирост пропускной способности от снижения нагрузки на пропускную способность памяти и более высокой утилизации вычислений; реальное ускорение зависит от оборудования и того, является ли развертывание ограниченным по вычислениям (compute-bound) или по памяти (memory-bound). На оборудовании, ограниченном памятью, что типично для инференса LLM с большими батчами, ускорение приближается к заявленным значениям. На оборудовании, ограниченном вычислениями, с очень маленькими батчами, ускорение небольшое.
Выбор уровня квантования
Выбор уровня квантования зависит от трех ограничений: допустимого отклонения точности, доступного оборудования и требований к задержке развертывания. Решение редко бывает теоретическим – оно диктуется конкретной моделью, конкретным бенчмарком, который важен для сценария использования, и оборудованием, на которое нацелено развертывание.
Начните с FP16 или BF16, если оборудование может их вместить, а требования к точности строгие. BF16 обычно предпочитают FP16 за его более широкий динамический диапазон, который снижает проблемы потери значимости (underflow) во время вычисления внимания. Это базовый уровень для любого продакшен-развертывания, где GPU имеет достаточный объем VRAM.
Перейдите на FP8, если вы используете оборудование Hopper или Blackwell и хотите почти исходную точность с двукратной экономией памяти. FP8 – это оптимальная точка для развертываний в дата-центрах в 2026 году, предлагающая лучший баланс производительности и качества на современных GPU NVIDIA.
Используйте INT8 PTQ с AWQ или SmoothQuant, если FP8 недоступен на вашем оборудовании и потеря точности в диапазоне 1-2% приемлема. INT8 остается надежным выбором для старых архитектур GPU (A100, V100), где FP8 не поддерживается.
Используйте INT4 PTQ, когда VRAM является жестким ограничением, а потеря точности 3-8% допустима. Это распространено для периферийного развертывания, потребительского оборудования и сценариев, где запуск модели 30B локально на INT4 предпочтительнее удаленного запуска модели 7B на FP16. Выбирайте GPTQ для более широкой совместимости с инструментами или AWQ ради дополнительных нескольких процентов точности.
Оставьте QAT для моделей с наивысшей ценностью, где точность INT4 должна соответствовать или превышать PTQ, или там, где требуется INT2. QAT – это значительное мероприятие, и оно оправдано только тогда, когда модель достаточно велика, чтобы экономия на параметр перевешивала стоимость обучения. Если провайдер модели выпускает чекпойнты QAT – как Google сделала для Gemma 4 – используйте их, а не пытайтесь внедрять QAT внутри компании.
Один практический принцип: квантуйте самую маленькую модель, которая соответствует требованиям к точности на FP16, а не самую большую модель, доведенную до минимально жизнеспособной разрядности бит. Модель 13B на INT8 с потерей 2% часто более способна, чем модель 30B на INT2 с потерей 12%, поскольку точность при более низкой разрядности не масштабируется линейно с количеством параметров.
Оптимизация KV-кэша
KV-кэш является единственным крупнейшим потребителем памяти во время авторегрессионного инференса. Понимание того, почему это так, и понимание стратегий, уменьшающих его объем, необходимо для создания экономически эффективных систем обслуживания.
Проблема KV-кэша
Авторегрессионные языковые модели генерируют текст по одному токену за раз. На каждом шаге модель вычисляет внимание между новым токеном запроса (query) и каждым ранее сгенерированным или предложенным токеном. Пересчет векторов ключей (key) и значений (value) с нуля на каждом шаге сделал бы генерацию запретно дорогой: обработка контекста длиной L потребовала бы O(L^2) вычислений внимания.
KV-кэш устраняет эту избыточность. После вычисления векторов ключей и значений для токена при его первом появлении эти векторы кэшируются в памяти GPU. Последующие шаги внимания считывают кэшированные векторы вместо их пересчета. Это снижает вычисления на токен с O(L^2) до O(L), обеспечивая приемлемые скорости генерации.
Размер кэша растет пропорционально окну контекста, размеру батча, глубине модели и скрытой размерности. Для модели Llama 3 70B с батчем 32 и окном контекста 128K один только KV-кэш может превысить 100 ГБ. Эта единая тензорная структура часто потребляет больше памяти, чем сами веса модели, и она ограничивает достижимые размеры батчей более напрямую, чем любой другой фактор.
FlashAttention: учет ввода-вывода
Стандартные реализации внимания материализуют полную матрицу внимания в HBM, что потребляет огромное количество памяти и пропускной способности памяти. FlashAttention (и ее последующие итерации v2/v3) – это алгоритм точного внимания, учитывающий ввод-вывод (IO-aware), который фундаментально изменил масштабирование LLM.
Вместо чтения и записи всей матрицы внимания в HBM, FlashAttention разбивает вычисления на блоки (tiles). Он загружает тайлы Q, K и V из HBM в на-чиповую SRAM GPU, вычисляет внимание поблоочно и записывает обратно в HBM только выходные тайлы. Сам KV-кэш остаётся в HBM; FlashAttention избегает “стены памяти” благодаря тому, что никогда не материализует полную матрицу внимания N×N. Это снижает трафик HBM примерно до O(n + s) вместо O(n × s) для размера батча n и длины последовательности s, позволяя окнам контекста масштабироваться до сотен тысяч токенов без падения пропускной способности.
Сегментированный Prefill (Chunked Prefill)
Перед обсуждением стратегий управления кэшем стоит упомянуть Chunked Prefill – технику, которая стала стандартом в современных фреймворках обслуживания, таких как vLLM и SGLang.
Когда поступает запрос с очень длинным промптом (например, 100K токенов), его обработка за один проход prefill монополизировала бы GPU на секунды, блокируя все остальные запросы и вызывая массовые всплески TTFT для параллельных запросов декодирования. Chunked Prefill решает эту проблему, разбивая фазу prefill на более мелкие чанки (например, по 4K или 8K токенов за раз) и чередуя их с шагами декодирования из других запросов.
Планировщик обрабатывает один чанк длинного промпта, затем переключается на обработку токенов декодирования из других активных запросов, затем возвращается к следующему чанку. Это поддерживает GPU в постоянно загруженном состоянии, сохраняет низкий TTFT для коротких запросов и предотвращает всплески памяти, которые могут вызвать ошибки OOM. Chunked Prefill особенно важен для смешанных рабочих нагрузок, где длинно-контекстные и коротко-контекстные запросы поступают одновременно.
PagedAttention (vLLM)
PagedAttention проводит аналогию с виртуальной памятью операционной системы. Вместо требования одного непрерывного блока памяти GPU для KV-кэша каждого запроса, он выделяет кэш в несмежных блоках. Каждый блок содержит фиксированное количество токенов – обычно 16 или 32 – и vLLM выделяет блоки по требованию по мере роста длины последовательности.
Этот подход устраняет внутреннюю фрагментацию. При непрерывном распределении каждый запрос резервирует VRAM для своей максимально возможной длины контекста, даже если он генерирует лишь несколько токенов. При непрерывном распределении развертывание с запросами, варьирующимися от ответов в 200 токенов до 128K токенов, тратит впустую огромное количество зарезервированной, но неиспользуемой памяти. PagedAttention выделяет только те блоки, которые запрос фактически использует.
Вторичным преимуществом является непрерывная пакетная обработка (continuous batching). Новые запросы могут входить в цикл генерации в любое время, не дожидаясь завершения существующих запросов, поскольку их блоки KV-кэша чередуются с существующими блоками в памяти GPU. Таблица блоков PagedAttention сопоставляет логические позиции токенов каждого запроса с физическими блоками GPU, прозрачно поддерживая это чередование.
Автоматическое кэширование префиксов (Automatic Prefix Caching, APC) встроено в планировщик vLLM. Когда несколько запросов используют один и тот же системный промпт или общий префикс, vLLM вычисляет хеш каждого блока и проверяет, существует ли этот хеш уже в памяти. Если да, vLLM повторно использует кэшированный блок вместо его пересчета. Это хорошо работает для точных совпадений префиксов (например, идентичных системных промптов), но менее эффективно для частичных перекрытий или когда префиксы расходятся в начале последовательности.
Экономия памяти от PagedAttention существенна в реальных развертываниях. По сравнению с непрерывным распределением, vLLM достигает примерно на 20 процентов лучшего использования VRAM в типичных рабочих нагрузках API со смешанными длинами последовательностей. При включенном APC экономия может достигать 30-40% для рабочих нагрузок с высоким повторным использованием префиксов.
RadixAttention (SGLang)
RadixAttention развивает кэширование префиксов дальше, строя дерево radix (бор) над блоками KV-кэша. Каждый узел в дереве представляет префикс токенов, а его дочерние ребра представляют продолжения. Когда поступает новый запрос, SGLang проверяет дерево radix на наличие существующих узлов, соответствующих префиксу запроса, и повторно использует их кэшированные блоки KV.
Эта структура наиболее эффективна в рабочих нагрузках чат-API. Рассмотрим систему, в которую поступают тысячи запросов с одним и тем же системным промптом на 4K токенов, за которым следуют сообщения, специфичные для пользователя. В RadixAttention системный промпт на 4K токенов кэшируется один раз в дереве radix, и все последующие запросы разделяют эти блоки. Только специфичный для пользователя суффикс требует новых вычислений KV и выделения памяти.
Ключевым преимуществом RadixAttention перед кэшированием префиксов на уровне блоков является повторное использование с более высокой степенью детализации. Если два запроса имеют общий префикс в 4K, но затем расходятся, а позже имеют еще один общий сегмент в 1K, RadixAttention может кэшировать и повторно использовать оба сегмента независимо. Кэширование на уровне блоков закэшировало бы только начальный префикс 4K и пропустило бы более позднее перекрытие.
Дерево radix требует активного обслуживания. По мере завершения запросов их уникальные узлы суффиксов становятся кандидатами на вытеснение (eviction). SGLang использует стратегию динамической обрезки, которая отслеживает счетчики ссылок на узлы: когда ни один активный запрос не нуждается в узле суффикса, блоки этого узла освобождаются для перераспределения. Политика вытеснения на основе подсчета ссылок гарантирует, что память остается ограниченной даже при сильной смене префиксов.
SGLang обычно обеспечивает экономию памяти на 30-50 процентов по сравнению с PagedAttention в рабочих нагрузках, где часто используется совместное использование префиксов. Когда префиксы полностью уникальны – например, суммаризация документов с разными документами для каждого запроса – преимущество RadixAttention уменьшается и приближается к базовому уровню PagedAttention.
GQA, MQA и MLA (уровень архитектуры)
Multi-Query Attention (MQA), Grouped-Query Attention (GQA) и Multi-head Latent Attention (MLA) уменьшают размер KV-кэша за счет архитектурного проектирования, а не управления во время выполнения.
Стандартное многоголовое внимание поддерживает отдельные головы ключей и значений для каждой головы запроса. MQA объединяет все головы запросов для совместного использования одной головы KV, уменьшая кэш в количество раз, равное числу голов внимания.
GQA находит золотую середину. Вместо одной общей головы KV он группирует несколько голов запросов вместе, причем каждая группа разделяет одну голову KV. Например, Llama 3 405B использует 128 голов запросов, сгруппированных в 8 групп голов KV, что достигает 16-кратного уменьшения размера KV-кэша по сравнению со стандартным многоголовым вниманием. Llama 3 70B использует 64 головы запросов с 8 головами KV (8-кратное уменьшение), а Llama 3 8B использует 32 головы запросов с 4 головами KV (8-кратное уменьшение).
Multi-head Latent Attention (MLA) представляет собой самое агрессивное сжатие кэша на сегодняшний день. Популяризированный моделями DeepSeek-V2 и V3, MLA применяет совместное сжатие низкого ранга к векторам ключей и значений. Вместо хранения полных матриц K и V, MLA проецирует их в гораздо меньшее скрытое пространство с помощью матрицы понижающей проекции. В KV-кэше хранится только этот сжатый скрытый вектор. Во время внимания повышающая проекция восстанавливает полные векторы K и V на лету.
Коэффициент сжатия MLA впечатляет: для DeepSeek-V3 KV-кэш сокращается примерно до 5-10% от размера стандартного многоголового внимания, что даже меньше, чем у GQA-8. Потеря качества незначительна, поскольку матрицы повышающей и понижающей проекций изучаются совместно с остальной моделью во время обучения. MLA стала стандартной архитектурой внимания для новых моделей MoE и плотных моделей с длинным контекстом, где давление KV-кэша является доминирующим ограничением.
Компромисс между GQA и стандартным вниманием имеет один нюанс. Некоторые бенчмарки показывают незначительную потерю качества при переходе от полного многоголового внимания к GQA с разумными размерами групп. Другие бенчмарки показывают измеримую деградацию в конкретных задачах на рассуждение или задачах “иголка в стоге сена”. На практике экономия KV-кэша от GQA делает ее доминирующим выбором для моделей с числом параметров выше 13B, поскольку уменьшенный кэш позволяет использовать большие размеры батчей, что улучшает пропускную способность в большей степени, чем любой регресс качества ее снижает.
MQA, имеющая только одну голову KV, достигает еще большего сокращения – до 128 раз для моделей со 128 головами внимания. Однако потеря качества при MQA более выражена, чем при GQA, и большинство современных моделей оставляют MQA для конкретных вложений (embedding) или подсетей извлечения (retrieval), а не для основного стека трансформера.
Квантование KV-кэша
Помимо уменьшения количества кэшированных векторов (GQA/MLA) или управления их распределением (PagedAttention), современные стеки обслуживания также квантуют сам KV-кэш. В развертываниях с длинным контекстом и большими батчами KV-кэш может потреблять 60-80% общей VRAM, что делает его квантование более влиятельным, чем только квантование весов.
Наиболее распространенный подход хранит KV-кэш в FP8 (с использованием формата E4M3) с по-головными (per-head) или по-токенными (per-token) масштабными коэффициентами, вычисляемыми динамически во время генерации. Поскольку распределение значений KV относительно стабильно между слоями и головами, KV-кэш FP8 влечет незначительную потерю качества – обычно менее 0,2% на стандартных бенчмарках – при этом вдвое уменьшая объем памяти кэша.
Для еще более агрессивного сжатия в TensorRT-LLM и экспериментальных сборках vLLM доступны форматы KV-кэша INT8 и INT4. Они требуют более сложных стратегий масштабирования (например, per-token-per-head или сглаженного квантования), чтобы избежать искажения оценок внимания, но могут уменьшить память кэша в 4-8 раз по сравнению с FP16.
Комбинация является мощной: модель DeepSeek-V3, обслуживаемая с MLA (сжатие кэша в 5-10 раз на уровне архитектуры), весами FP8 (2x) и KV-кэшем FP8 (2x), достигает размера памяти, сопоставимого с плотной моделью 70B в FP16, обеспечивая при этом результаты уровня frontier-моделей.
Таблица сравнения методов для KV-кэша
| Техника | Уменьшение кэша | Совместное использ. префиксов | Фреймворк | Лучшая рабочая нагрузка |
|---|---|---|---|---|
| PagedAttention + APC | ~20-40% лучше утил. | Точное совпадение | vLLM | Общий API |
| RadixAttention | ~30-50% при общих | Частичное совпадение | SGLang | Чат, общие промпты |
| MQA | 16-128x | Н/Д | Архитектура модели | Все |
| GQA | 4-16x | Н/Д | Архитектура модели | Все |
| MLA | 5-10x | Н/Д | Архитектура модели | Длинный контекст, MoE |
| FP8 KV Cache | 2x | Н/Д | vLLM, TensorRT-LLM | Все |
| Offloading (CPU/NVMe) | Неограниченно | Н/Д | Любой | Экстремальный батч |
Эти техники не являются взаимоисключающими. Продакшен-развертывание может использовать MLA или GQA на уровне архитектуры для уменьшения размера кэша в 5-16 раз, квантовать кэш в FP8 для дополнительного 2-кратного уменьшения, использовать PagedAttention или RadixAttention для управления оставшимся кэшем с минимальной фрагментацией, применять Chunked Prefill для изящной обработки запросов с длинным контекстом и использовать TP (Tensor Parallelism) для распределения вычислений между GPU. Комбинация раздвигает пределы размера батча дальше, чем любая отдельная техника.
Один из новых подходов для экстремальных рабочих нагрузок – это офлоадинг (перенос) KV-кэша в память CPU или на NVMe SSD. Для запросов с очень длинными контекстами, которые превышают память GPU, фреймворки могут хранить неактивные блоки кэша в системной RAM или на быстром NVMe-накопителе и загружать их обратно по требованию через RDMA. Системы вроде FlexGen и InfiniStore демонстрируют, что контексты на миллион токенов достижимы на одном GPU при агрессивном офлоадинге, хотя и ценой более высокой задержки на токен. Эта стратегия вводит задержку, но позволяет обслуживать запросы, которые в противном случае были бы отклонены. Она остается запасным вариантом, а не основной стратегией, зарезервированной для крайних случаев, когда окно контекста и размер батча совместно превышают емкость GPU.
Глоссарий
| Термин | Определение |
|---|---|
| APC (Automatic Prefix Caching) | Встроенный в vLLM механизм кэширования префиксов. Хэширует блоки KV-кэша и повторно использует их, когда идентичные префиксы встречаются в разных запросах. Эффективен для точного совпадения префиксов (например, общих системных промптов). |
| AWQ (Activation-Aware Weight Quantization) | Метод PTQ, который определяет “важные” каналы с большими амплитудами активаций и сохраняет их в более высокой точности, в то же время агрессивно квантуя менее важные каналы. Последовательно достигает лучшей точности, чем GPTQ, при той же разрядности бит. |
| BF16 | BFloat16 – 16-битный формат с плавающей запятой с 8-битной экспонентой и 7-битной мантиссой. Обеспечивает более широкий динамический диапазон, чем FP16, снижая потери значимости (underflow) при вычислении внимания. Нативно поддерживается GPU Hopper и Blackwell. |
| Разложение Холецкого (Cholesky decomposition) | Метод факторизации матриц, используемый GPTQ для аппроксимации матрицы Гессе для каждого слоя весов, что позволяет выполнять последовательное квантование по столбцам, минимизируя распространение ошибки. |
| Chunked Prefill | Техника, которая разбивает фазу prefill длинных запросов на более мелкие чанки (например, 4K–8K токенов) и чередует их с шагами декодирования из других запросов. Предотвращает монополизацию GPU и всплески TTFT. |
| E4M3 | Формат FP8: 4-битная экспонента, 3-битная мантисса. Стандартный формат для весов и активаций модели, обеспечивающий достаточный динамический диапазон при помещении в нативные FP8 Tensor Cores. |
| E5M2 | Формат FP8: 5-битная экспонента, 2-битная мантисса. Используется в основном во время обучения для градиентов, предлагая более широкий динамический диапазон ценой точности. |
| FakeQuant | Тренировочный компонент QAT, вставляемый в граф вычислений. Во время прямого прохода квантует значения до целевой точности и деквантует обратно в FP32/FP16, симулируя потерю информации от целочисленной арифметики. |
| FlashAttention | Алгоритм точного внимания, учитывающий ввод-вывод (IO-aware), который разбивает вычисления Q, K и V на тайлы в SRAM GPU, избегая записи полной матрицы внимания в HBM. KV-кэш остаётся в HBM; тайлы загружаются поблочно во время выполнения объединенного ядра (fused kernel). Снижает трафик HBM с O(n×s) до O(n+s) для батча n и последовательности s. (Версия v3 оптимизирована для архитектуры Hopper.) |
| FP8 | 8-битный формат чисел с плавающей запятой. Точность по умолчанию для инференса LLM в дата-центрах на GPU H100, H200 и B200. Обеспечивает экономию памяти ~2x по сравнению с FP16 с незначительной потерей точности (0,1-0,5%). |
| GGUF | Универсальный формат сериализации для квантованных моделей, используемый llama.cpp. Хранит веса, метаданные квантования, словарь и конфигурацию архитектуры в одном переносимом файле. |
| GQA (Grouped-Query Attention) | Вариант внимания, при котором несколько голов запросов разделяют одну пару голов KV. Llama 3 405B использует 128 голов запросов с 8 группами KV (16-кратное уменьшение кэша). Llama 3 8B использует 32 головы запросов с 4 группами KV (8-кратное уменьшение). Золотая середина между MQA и стандартным MHA. |
| GPTQ | Метод квантования после обучения, который выполняет послойное квантование с использованием гессианской информации второго порядка. Квантует столбцы весов последовательно, вычисляя матрицу восстановления на каждом шаге для компенсации ошибки. Хорошо работает для INT4 и INT3. |
| Гессиан (Hessian) | Матрица вторых частных производных. В GPTQ Гессиан аппроксимирует, насколько чувствительна функция потерь к изменениям в каждом весе, направляя порядок квантования для минимизации ошибки. |
| INT2 | 2-битное целочисленное квантование. Экстремальное сжатие (экономия памяти ~16x по сравнению с FP16), но значительная потеря точности (5-15%). Требует QAT для рабочих результатов. |
| INT4 | 4-битное целочисленное квантование. Снижает память весов ~4x по сравнению с FP16. PTQ обычно влечет потерю точности 3-8%; QAT снижает ее до 1-3%. |
| INT8 | 8-битное целочисленное квантование. Экономия памяти ~2x по сравнению с FP16 с потерей точности 1-2%. Надежный выбор для оборудования без нативной поддержки FP8. |
| Квантование KV-кэша (KV Cache Quantization) | Квантование кэшированных векторов ключей и значений (обычно в FP8 или INT8) вместо FP16. Снижает объем самого крупного потребителя VRAM во время авторегрессионного инференса. |
| MLA (Multi-head Latent Attention) | Агрессивное сжатие кэша, которое проецирует векторы K и V в меньшее скрытое пространство, сохраняя в KV-кэше только сжатое представление. Во время внимания повышающая проекция восстанавливает полные векторы. Популяризировано DeepSeek-V2/V3, достигает 5-10x уменьшения кэша. |
| MQA (Multi-Query Attention) | Вариант внимания, при котором все головы запросов разделяют одну голову KV. Максимальное уменьшение кэша (до 128x), но более выраженная потеря качества, чем при GQA. |
| Поканальное квантование (Per-channel) | Каждый выходной канал (нейрон) получает свой собственный масштабный коэффициент, лучше сохраняя детали для каналов с выбросами, чем потензорное. Минимальные накладные расходы и стандарт для квантования весов INT4/INT8. |
| Погрупповое квантование (Per-group) | Каждый канал разбивается на небольшие группы (обычно по 32 или 64 элемента), каждая из которых квантуется независимо. Используется в GPTQ и GGUF. Балансирует сохранение точности с накладными расходами на метаданные масштаба. |
| Потензорное квантование (Per-tensor) | Единый масштабный коэффициент применяется ко всему тензору весов. Наименьшие накладные расходы, но худшая точность для моделей с каналами-выбросами. |
| PagedAttention | Техника управления KV-кэшем, вдохновленная виртуальной памятью ОС. Выделяет кэш несмежными блоками (обычно 16–32 токена на блок), устраняя фрагментацию и обеспечивая непрерывное батчирование. Предложена Kwon et al. (SOSP 2023). |
| PTQ (Post-Training Quantization) | Преобразование предварительно обученной модели в более низкую точность без градиентного дообучения. Требует лишь небольшого набора данных для калибровки. Быстрый (от минут до часов), но имеет жесткий потолок точности при агрессивных разрядностях бит. |
| Q4_0 | 4-битное квантование GGUF с погрупповым масштабированием. Базовый уровень квантования GGUF, балансирующий использование памяти и точность. |
| Q4_K_M | 4-битное квантование GGUF со смешанной точностью. Большинство весов в 4 битах, но каналы с выбросами сохраняются в Q6 или Q8. Суффикс “M” выбирает среднюю детализацию. Лучшее соотношение качества к памяти для инференса на CPU. |
| Q5_K_M | Как Q4_K_M, но с 5-битной базовой точностью. Возвращает ~1% точности ценой ~12% дополнительной памяти. |
| Q8_0 | 8-битное погрупповое квантование GGUF. Почти безпотерная точность (~0,2% потерь) примерно при половине объема памяти от FP16. |
| QAT (Quantization-Aware Training) | Обучение модели с симуляцией квантования (узлы FakeQuant + STE), чтобы она научилась работать в условиях ограничений точности. Превосходная точность по сравнению с PTQ, особенно при INT2 и агрессивном INT4. Требует полной инфраструктуры обучения. |
| QoQ (quattuor-octo-quattuor) | Метод от QServe для квантования W4A8KV4. QoQ — это “4-8-4” на латыни, что соответствует конфигурации INT4 веса, INT8 активации и INT4 KV-кэша. Применяет стратегии вращения и сглаживания для одновременного использования всех трёх. |
| QuaRot | Метод квантования W4A4, который применяет матрицы вращения к распределениям весов перед квантованием, устраняя выбросы и включая полные вычисления INT4 (и веса, и активации). Точность сопоставима с W4A16 PTQ. |
| RadixAttention | Кэширование префиксов на основе дерева (бор) от SGLang для блоков KV-кэша. Более мелкозернистое повторное использование, чем блочный APC в vLLM – может кэшировать и разделять несмежные сегменты префиксов между запросами. Лучше всего для чат-нагрузок с общими промптами. |
| STE (Straight-Through Estimator) | Тренировочный трюк QAT, который пропускает градиенты напрямую через недифференцируемую функцию квантования, аппроксимируя ее как тождественную функцию во время обратного распространения ошибки. Позволяет сквозное обучение несмотря на целочисленную арифметику. |
| SmoothQuant | Метод PTQ, который перераспределяет сложность квантования с активаций на веса с использованием поканальных сглаживающих коэффициентов. Уменьшает масштаб крупных пред-активаций и соответственно увеличивает масштаб строк весов, допуская агрессивное квантование активаций. |
| Офлоадинг KV-кэша (KV Cache Offloading) | Хранение неактивных блоков KV-кэша в памяти CPU или на NVMe SSD при исчерпании памяти GPU и их загрузка обратно по требованию через RDMA. Используется FlexGen и InfiniStore для обеспечения контекстов в миллион токенов на одном GPU. Добавляет задержку на токен; применяется для экстремальных нагрузок. |
| W4A16 | Квантование: 4-битные веса / 16-битные активации. Веса хранятся в INT4, активации вычисляются в FP16. Более простая калибровка, но даёт ~2x общей экономии пропускной способности памяти (только веса сжимаются в 4 раза), без ускорения вычислений на Tensor Cores. |
| W4A4 | Квантование: 4-битные веса / 4-битные активации. И веса, и активации в INT4, что обеспечивает полную пропускную способность INT4 Tensor Cores на Hopper и позже (~8x ускорение). Требует QuaRot для поддержания качества. |
Ссылки
- Квантование – после обучения (PTQ)
- GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers. arXiv:2210.17323
- AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration. arXiv:2306.00978
- SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models. arXiv:2211.10438
- Квантование – W4A4 и на основе вращения
- QuaRot: Outlier-Free 4-Bit Inference in Rotated LLMs. arXiv:2404.00456
- QServe: W4A8KV4 Quantization and System Co-design for Efficient LLM Serving (QoQ algorithm). arXiv:2405.04532
- Обучение с учетом квантования (QAT)
- Gemma 4 Technical Report (QAT 4-bit and 2-bit checkpoints). arXiv:2607.02770
- Внимание и KV-кэш
- FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness. arXiv:2205.14135
- Fast Transformer Decoding: One Write-Head is All You Need (MQA). arXiv:1911.02150
- GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints. arXiv:2305.13245
- DeepSeek-V2: A Strong, Economical, and Efficient Mixture-of-Experts Language Model (MLA). arXiv:2405.04434
- DeepSeek-V3 Technical Report (MLA + MoE + MTP). arXiv:2412.19437
- Управление KV-кэшем
- Efficient Memory Management for Large Language Model Serving with PagedAttention (vLLM). arXiv:2309.06180
- SGLang: Efficient Execution of Structured Language Model Programs (RadixAttention). arXiv:2312.07104
Предыдущая: Часть 1 – Архитектура и метрики
Следующая: Часть 3 – Параллелизм и скорость рассматривает предсказание нескольких токенов и стратегии распределенного инференса.