Руководство по квантизации моделей: от основ до продакшен-сервинга

Автоматический перевод Эта статья была автоматически переведена с оригинальной английской версии.

Квантизация использует меньше битов для представления значений модели. В пайплайне сервинга можно квантизовать веса, активации, KV cache или их комбинацию, причем каждая цель решает свою задачу сервинга.

Выбирайте цель исходя из текущего боттлнека: память под веса, вычисления активаций, размер KV cache, ядра, железо, калибровочные данные или качество. 4-битная модель может поместиться в VRAM, но работать медленно из-за неоптимизированного ядра, как показывает бенчмарк JarvisLabs для vLLM. FP8 хорошо работает на железе NVIDIA Hopper с совместимым рантаймом, но не дает нативных преимуществ на неподдерживаемых GPU. Матрица совместимости TensorRT-LLM показывает поддерживаемые варианты. При длинном контексте или высокой конкурентности квантизация KV cache может сэкономить больше памяти, чем квантизация весов.

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

Краткое сравнение артефактов и методов см. в материале Форматы квантизации LLM.

Как пользоваться этим руководством по квантизацииКак пользоваться этим руководством по квантизации


1. Начинайте с боттлнека

Перед выбором разрядности определите, что ограничивает workload. Это может быть память под веса модели, вычисления на этапе префилла, пропускная способность при декоде или KV cache, а не численная точность сама по себе.

Типичные боттленеки и отправные точки:

Если проблема в этомНачните отсюдаТипичные инструментыПроверьте до деплоя
Веса модели не помещаются в VRAMWeight-only квантизация W4A16AWQ или GPTQ с llm-compressor или GPTQModelPerplexity, кодинг, ризонинг, следование инструкциям
Сервинг с высоким throughput упирается в вычисленияFP8 или INT8 W8A8FP8 PTQ, SmoothQuant, TensorRT-LLM, vLLMThroughput, TTFT, точность на задачах
Длинный контекст или высокая конкурентность заполняют GPUКвантизация KV cachevLLM, TensorRT-LLM или Transformers QuantizedCacheRetrieval в длинном контексте, латентность, безопасность и качество
Локальный инференс на CPU, Apple Silicon или десктопеФайлы GGUF с локальными tensor-encodingllama.cpp, Ollama, LM StudioЛатентность промпта, использование RAM, выбранный tensor encoding и субъективное качество вывода
Адаптерный файн-тюнинг должен помещаться на одном GPUNF4 / QLoRAbitsandbytes, peftLoss файн-тюнинга и качество объединенной модели
Пайплайн генерации изображений слишком большой или медленныйСпецифичная для diffusion INT4 или FP8SVDQuant, Nunchaku, torchao, NVIDIA ModelOptВизуальные артефакты, соответствие промпту, латентность, VRAM

Используйте эту таблицу как карту. В следующих разделах объясняется, почему эти отправные точки различаются.

Обозначения в рецептах сервинга

  • W{x}A{y} указывает точность для поддерживаемых операций с весами и активациями, обычно в GEMM-путях serving engine. W4A16 хранит веса в 4-битном формате, а активации оставляет в 16-битной точности. W8A8 использует 8-битные веса и активации в поддерживаемых вычислительных путях, но автоматически не определяет persistent storage dtype каждого runtime-тензора.
  • FP8, INT8, INT4, NF4 — это числовые форматы. Они определяют, какие значения можно представить.
  • GPTQ, AWQ, SmoothQuant, QuaRot — это алгоритмы. Они определяют, как преобразовать обученную модель в формат с меньшей точностью.
  • GGUF — файловый формат, который хранит тензоры и метаданные для GGML- и llama.cpp-подобных рантаймов. Файл GGUF может содержать неквантизованные типы тензоров, например F16, BF16 или F32, а также квантизованные encoding. Доступные пресеты включают Q4_K_M, Q5_K_M, Q8_0, IQ*, TQ* и MXFP4. Выбранный tensor encoding определяет вариант квантизации. Сам по себе GGUF не описывает serving-рецепт CUDA в формате FP8 W8A8.
  • KV cache — это кэш аттеншна, используемый во время генерации. В нем хранятся предыдущие keys и values, чтобы модель не пересчитывала весь диалог при генерации каждого токена.
  • Квантизация KV cache сохраняет кэшированные activation-тензоры key/value в формате с меньшей точностью — например, FP8, INT8, INT4 или INT2, в зависимости от поддержки рантайма. Это отличается от prefix caching, PagedAttention и offload: они определяют, переиспользуются ли записи кэша, как они выделяются и где хранятся.
  • GEMM означает general matrix multiply — умножение матриц общего вида. Большая часть времени инференса трансформера уходит на умножение матриц.

2. Квантизация — это управляемое округление

Квантизация отображает значения высокой точности в меньшее множество представимых значений — это базовое определение, используемое и в концептуальном руководстве по квантизации Hugging Face Optimum, и в TensorRT-LLM. Вы экономите память и пропускную способность, но вносите ошибку округления.

INT4 предоставляет лишь 16 дискретных значений, поэтому отображение весов BF16 на эту сетку создает ошибку округления. Методы вроде GPTQ, AWQ и SVDQuant направлены на сохранение выбросов и снижение ошибки реконструкции. Хорошее отображение экономит память с небольшой потерей качества. Плохое ухудшает ризонинг, следование инструкциям или визуальную достоверность.

Симметричное и асимметричное отображение

Согласно affine mapping, используемому в распространенных руководствах по квантизации, квантизация отображает непрерывное float-значение x[β,α]x \in [\beta, \alpha] на дискретную сетку.

  • xx — исходное значение высокой точности.
  • xqx_q — квантизованное значение.
  • ss — scale, или размер шага.
  • zz — zero point, целочисленная позиция, представляющая 0.0.
  • [qmin,qmax][q_{\min}, q_{\max}] — целевой диапазон целых чисел. Знаковые 4-битные значения часто используют [7,7][-7, 7].

Симметричная квантизация центрирует сетку вокруг нуля и задает z=0z = 0:

s=max(x)qmaxs = \frac{\max(|x|)}{q_{\max}} xq=clip(round(xs),qmin,qmax)x_q = \text{clip}\left(\text{round}\left(\frac{x}{s}\right), q_{\min}, q_{\max}\right)

Это удобно для железа, поскольку runtime-математике не нужно вычитать смещение zero point. Стек квантизации PyTorch предоставляет эти affine scale и zero-point параметры как примитивные параметры квантизации в torchao.

Асимметричная квантизация сдвигает сетку, чтобы покрыть скошенные диапазоны:

s=αβqmaxqmins = \frac{\alpha - \beta}{q_{\max} - q_{\min}} z=round(βs)+qminz = \text{round}\left(\frac{-\beta}{s}\right) + q_{\min} xq=clip(round(xs)+z,qmin,qmax)x_q = \text{clip}\left(\text{round}\left(\frac{x}{s}\right) + z, q_{\min}, q_{\max}\right)

Такая сдвинутая сетка лучше сохраняет активации, принимающие только положительные значения, но смещение добавляет вычисления, если ядро не обрабатывает его эффективно.

Как квантизация отображает значения высокой точности в бакеты низкой точностиКак квантизация отображает значения высокой точности в бакеты низкой точности

Гранулярность scale имеет значение

Scale-фактор может охватывать весь tensor весов, один канал или небольшую группу значений. В документации vLLM по FP8 KV cache используется то же различие между стратегиями scale per-tensor и per-attention-head. Меньшие группы обычно лучше сохраняют качество, но требуют больше метаданных scale.

Гранулярность scaleЧто использует один scaleВлияние на качество и выполнение
Per tensorВся матрица весовТребует мало метаданных, но один выброс может растянуть сетку и снизить точность по всему слою.
Per channelОдна выходная строкаНе дает каналам с узкими диапазонами делить широкий диапазон другого канала. Многие 8-битные пути для весов используют такую гранулярность.
Per groupБлок в строке, обычно 64 или 128 значенийОграничивает влияние выброса небольшим блоком ценой дополнительных scale. AutoGPTQ использует group_size=128 в своих примерах GPTQ.

Веса статичны, поэтому их scale можно вычислить offline до загрузки модели. Активации меняются с каждым токеном, поэтому их диапазоны зависят от workload.

Масштабирование активацийКогда runtime выбирает scaleПреимуществоРежим сбоя или стоимость
StaticOffline на основе датасета для калибровкиНе требует вычислять scale во время инференса.Промпты за пределами калиброванной длины или распределения могут обрезать пики активаций и ухудшить вывод.
DynamicВо время каждого forward passАдаптируется к текущим значениям активаций и смеси промптов.Вычисление диапазонов на каждом слое добавляет нагрузку и требует оптимизированных ядер.

KV cache занимает промежуточное положение. Keys и values изначально являются runtime activation-тензорами: каждый слой вычисляет их из hidden states во время forward pass. После генерации они перестают быть временными промежуточными результатами matmul и становятся persistent serving state, который attention считывает при обработке следующих токенов.

Serving engine может хранить это состояние в формате меньшей точности и держать scale-метаданные рядом с ним. Quantized KV Cache в vLLM, FP8 KV Cache в TensorRT-LLM и Transformers QuantizedCache предоставляют такую настройку.

Точность хранения кэша остается отдельной от точности активаций внутри linear-ядер. «Квантизация KV cache» обозначает одну оптимизацию кэша, а не все методы повторного использования, выделения или перемещения записей кэша.

PTQ и QAT выполняются на разных этапах

Post-training quantization, или PTQ, сжимает уже обученную модель. Quantization-aware training, или QAT, знакомит модель с шумом квантизации во время обучения, чтобы она могла адаптироваться.

МетодКогда изучаются диапазоныИспользуйте, когдаЦена
Weight-only PTQOffline для статичных весовМодель не помещается в память или decode упирается в bandwidthАктивации по-прежнему выполняются в 16-битном формате
Static PTQOffline на основе калибровочных промптовНужен быстрый W8A8-servingКалибровочные данные должны соответствовать production-трафику
Dynamic PTQRuntime, для каждого batch или activation pathРаспределения входов сильно различаютсяДополнительная runtime-нагрузка и более узкая поддержка железа
QATВо время обученияPTQ ломает качество чувствительной моделиПолная инфраструктура обучения и намного больше вычислений

Калибровочные данные должны быть похожи на трафик, который вы будете обслуживать. Например, путь калибровки KV cache в vLLM использует подготовленный датасет через llm-compressor. Если production-промпты — это длинные RAG-трейсы, короткие абзацы из Wikipedia дадут аккуратные цифры на бенчмарке и сломанный деплой. Калибровка выбирает статичные scale и диапазоны активаций или кэша на основе распределения коротких текстов; она не настраивает фиксированные параметры модели. Реальные промпты с длинным контекстом могут порождать другие паттерны активаций. Оценки квантизации на длинном контексте напрямую измеряют этот риск.


3. Числовые форматы определяют требования к железу

Числовой формат определяет, какие значения модель может представлять в памяти. Для эффективных вычислений нужны runtime-ядра и аппаратная поддержка той же разрядности и формата. TensorRT-LLM документирует и список рецептов, и матрицу поддержки железа.

ФорматХранение одного значенияХороший вариант по умолчаниюОсновной риск
BF16 / FP162 байтаБазовый инференс и сервинг, совместимый с обучениемВысокое потребление VRAM и большой трафик памяти
FP81 байтВысокопроизводительный W8A8-serving на Ada, Hopper, BlackwellНужны нативные FP8 tensor cores и поддержка рантайма
INT81 байтW8A8-serving на старом железе или hardware не от NVIDIAВыбросы активаций и чувствительность к статичной калибровке
INT40,5 байтаW4A16, когда основное ограничение — память под весаПотеря качества на небольших моделях и моделях с тяжелым ризонингом
FP4 / NVFP4~0,5 байтаЭксперименты эпохи Blackwell и ранние serving-путиСпецифичные для железа требования к компилятору и рантайму
Кодировки / пресеты llama.cpp GGUFПеременныйЛокальный инференс на CPU, Apple Silicon, десктопах и edgeGGUF — контейнер. Tensor encoding — это выбор квантизации.
NF40,5 байтаОбучение адаптеров через QLoRAОбычно неподходящий формат экспорта для production-serving

BF16 и FP16 используют по 16 бит, но распределяют точность по-разному и поэтому по-разному выходят из строя. BF16 сохраняет 8-битный диапазон экспоненты FP32 и реже переполняется. FP16 имеет больше бит мантиссы и более узкий диапазон экспоненты, поэтому пики активаций требуют большего внимания. В оценке Kurtic et al. BF16 явно используется как baseline при сравнении FP8-, INT8- и INT4-форматов сервинга.

У FP8 есть два распространенных варианта. E4M3 дает более высокую точность и обычно используется для forward-весов и активаций. E5M2 предоставляет больший динамический диапазон и лучше подходит для градиентов или нестабильных activation path. vLLM предоставляет оба dtype для FP8 E4M3 и E5M2 KV cache. В исследовании Kurtic et al. на ACL 2025, «Give Me BF16 or Give Me Death», FP8 W8A8 оказался практически lossless для семейства Llama-3.1 более чем на 500 000 оценок. Результат относится к этому семейству моделей, набору оценок и конфигурации сервинга. Для каждого деплоя по-прежнему нужен собственный quality gate.

Blackwell добавляет microscaling-форматы, такие как MXFP8 и NVFP4. Вместо одного scale для всего тензора или строки microscaling использует очень маленькие блоки. Объяснение NVFP4 от NVIDIA описывает 4-битные floating-point-значения в блоках по 16 элементов, с FP8 scale-факторами и scale верхнего уровня FP32. Такой подход должен обеспечить footprint, близкий к INT4, сохранив поведение floating point. Однако для него нужны соответствующая архитектура железа, компилятор и поддержка рантайма, поэтому TensorRT-LLM перечисляет поддержку FP4 и FP8 по поколениям GPU.


4. Weight-only и weight-activation квантизация

Обозначение WxAy описывает точность весов и активаций, которые по-разному нагружают GPU во время инференса.

Механика квантизации: weight-only против weight-activationМеханика квантизации: weight-only против weight-activation

На этапе prefill модель обрабатывает входной промпт. Этот этап обычно упирается в вычисления, поскольку GPU выполняет большие умножения матриц; поэтому рецепты W8A8 FP8/INT8 важны для сервинга, ориентированного на throughput.

На этапе decode модель генерирует по одному токену за раз. Этот этап часто упирается в пропускную способность памяти: GPU постоянно загружает веса из VRAM, чтобы получить следующий токен. Weight-only-методы вроде GPTQ и AWQ снижают это давление, уменьшая объем весов в байтах.

W4A16 сжимает веса, но оставляет активации в BF16 или FP16. GPU загружает меньше байтов весов, а затем деквантизует их обратно в формат более высокой точности для умножения. Это помогает при decode и проблемах с размещением модели в памяти. Вычислительно-зависимый prefill может почти не выиграть, поскольку математика по-прежнему выполняется в 16-битном формате.

W8A8 сжимает веса и activation-тензоры, используемые поддерживаемыми matmul-ядрами. Если железо имеет нативные tensor cores для вычислений низкой точности, serving engine может выполнять математику матриц напрямую в FP8 или INT8. Поэтому FP8 может ускорить high-throughput serving, снижая трафик памяти и используя более быстрые вычисления. KV cache имеет собственную настройку хранения, поэтому отдельно проверьте cache dtype или cache implementation рантайма.

Если модель едва помещается в VRAM, начните с weight-only квантизации, чтобы уменьшить footprint. Если модель помещается, но испытывает проблемы с throughput при больших batch, оцените FP8 или INT8 W8A8 для ускорения вычислительной фазы. Если проблемы с памятью возникают только в длинных диалогах, сначала оцените слагаемое KV cache. Проверьте квантизацию KV cache, если оно доминирует. Включайте prefix caching, если доминируют повторяющиеся префиксы.


5. Алгоритмы и runtime-ядра

Алгоритмы квантизации, такие как GPTQ и AWQ, определяют, как веса модели отображаются в формат меньшей точности. Runtime-ядра, такие как Marlin или кастомные ядра vLLM, — это низкоуровневый GPU-код, выполняющий умножение матриц. Сильно сжатая модель будет работать быстро только при наличии оптимизированного ядра для конкретного формата квантизации.

И алгоритм квантизации, и runtime-ядро влияют на результат сервингаИ алгоритм квантизации, и runtime-ядро влияют на результат сервинга

Бенчмарк vLLM от JarvisLabs для Qwen2.5-32B-Instruct на NVIDIA H200 наглядно показывает влияние ядра:

Квантизация / ядроPerplexity, меньше — лучшеPass@1, больше — лучшеThroughputTTFT
FP16 baseline6.5656.1%461 tok/s57.7 ms
AWQ6.8451.8%68 tok/s277.8 ms
GPTQ6.9046.3%277 tok/s107.1 ms
Marlin-GPTQ6.9745.7%712 tok/s51.9 ms
Marlin-AWQ6.8451.8%741 tok/s73.5 ms
GGUF Q4_K_M6.7451.8%93 tok/s958.0 ms
bitsandbytes6.6751.8%168 tok/s135.3 ms

Не переносите эти числа напрямую на свой стек. Они получены для одной модели, одного класса GPU и одной программной конфигурации. Они показывают более узкий вывод: название алгоритма в чекпоинте не говорит, насколько быстрым будет сервинг.

Например, AWQ и Marlin-AWQ используют одинаковые 4-битные веса. Реализация Marlin намного быстрее, потому что ее CUDA-ядро объединяет деквантизацию и умножение матриц в одну высокооптимизированную операцию GPU.

Бенчмарк baseline и сжатых вариантов на одной и той же смеси промптов и одним и тем же инструментом. Запускайте каждый вариант как сервер и задавайте ему стабильное API-имя модели; vllm bench serve отправляет запросы в этот API, а не загружает чекпоинт самостоятельно:

vllm serve ./outputs/Qwen2.5-32B-Instruct-AWQ-W4A16 \
  --served-model-name qwen2.5-32b-awq \
  --host 127.0.0.1 \
  --port 8000

vllm bench serve \
  --backend openai \
  --base-url http://127.0.0.1:8000 \
  --endpoint /v1/completions \
  --model qwen2.5-32b-awq \
  --dataset-name sharegpt \
  --num-prompts 200 \
  --input-len 1024 \
  --output-len 256

Отслеживайте throughput, TTFT, межтокенную латентность, использование памяти и качество на задачах. Если часть показателей движется в противоположных направлениях, именно этот trade-off нужно увидеть до выхода в production.

Меню алгоритмов

Используйте эту таблицу как карту, а не как рейтинг:

АлгоритмРаспространенный форматЧто стремится сохранитьОсновная стоимость
GPTQW4A16Послойную реконструкцию с оценками HessianМедленная калибровка и более сложная обработка
AWQW4A16 / W4A8Важные activation-каналыНужны калибровка и fused serving-ядра
SmoothQuantW8A8Поведение активаций INT8 за счет переноса масштаба выбросов в весаНастройка scale для каждой модели
QuaRot / SpinQuantW4A4 / W4A8Снижение давления activation-выбросов через rotationsСложность runtime-rotation
HQQW4A16 / W2A16Быстрое weight-only-сжатие без калибровкиНа очень низкой разрядности качество требует downstream-проверок
QLoRA (NF4)NF4Память для обучения адаптеровНе лучший вариант по умолчанию для сервинга
K-quants / IQ-quants в llama.cpp GGUFСмешанные tensor encoding низкой разрядностиКачество локального инференса на байтНе предназначены для облачного batch-serving

Toolchain активно развивается. AutoGPTQ был переведен в архив в апреле 2025 года, а AutoAWQпереведен в архив и официально deprecated в мае 2025 года. Для новых чекпоинтов compressed-tensors, используемых через vLLM, начинайте с llm-compressor. Используйте GPTQModel, если нужен актуальный GPTQ-путь с Marlin, Machete, memory-опциями для MoE или disk offload.

Pruning и distillation также снижают стоимость сервинга через отдельные workflow. Структурированная разреженность 2:4 удаляет веса по шаблону, который могут использовать sparse tensor cores NVIDIA. Distillation обучает меньшую student-модель имитировать большую и может хорошо работать на узких задачах. Включайте любой из этих вариантов в shortlist только при готовности проекта к дополнительной pruning- или training-работе.


6. Память для сервинга — это не только веса

Сжатый чекпоинт — лишь часть footprint памяти для сервинга. Перед тем как решать, достаточно ли квантизации весов, оцените весь runtime. PagedAttention показывает, что KV cache — один из главных компонентов serving-памяти.

VRAMserveQuantized Weights+KV Cache+Runtime Activations+Engine Overhead\text{VRAM}_{\text{serve}} \approx \text{Quantized Weights} + \text{KV Cache} + \text{Runtime Activations} + \text{Engine Overhead}

Offline-квантизация может выполняться послойно. Инструменты вроде llm-compressor загружают один transformer-блок, выполняют калибровку и математику квантизации, записывают сжатый блок и переходят к следующему. Пиковое потребление GPU-памяти при этом ближе к размеру крупнейшего активного слоя плюс калибровочные буферы. CPU RAM и диск для исходного чекпоинта все равно нужны, но GPU не обязательно хранит всю модель BF16.

Пиковое потребление GPU-памяти во время offline-квантизации может выглядеть так:

GPU PeakquantizeLargest Layer (BF16)+Calibration Activations+Method Buffers\text{GPU Peak}_{\text{quantize}} \approx \text{Largest Layer (BF16)} + \text{Calibration Activations} + \text{Method Buffers}

Сервинг предъявляет более жесткие требования. Весь сжатый чекпоинт должен постоянно находиться в памяти вместе с KV cache и runtime-буферами. KV cache растет вместе с длиной контекста и размером активного batch:

KV Cache (Bytes)=2×L×Hkv×D×Sctx×Bbatch×BytesPerValue\text{KV Cache (Bytes)} = 2 \times L \times H_{\text{kv}} \times D \times S_{\text{ctx}} \times B_{\text{batch}} \times \text{BytesPerValue}

Где:

  • LL — число слоев.
  • HkvH_{\text{kv}} — число key-value attention heads. Grouped-query attention уменьшает его, позволяя множеству query heads совместно использовать меньшее число KV heads.
  • DD — размерность каждой head, обычно 128 или 256.
  • SctxS_{\text{ctx}} — число токенов промпта плюс число сгенерированных токенов.
  • BbatchB_{\text{batch}} — активный serving batch.
  • BytesPerValue\text{BytesPerValue} — 2 для BF16 или FP16 и 1 для FP8 или INT8. Режим FP8 KV cache в vLLM — serving-пример, используемый в этой статье.

Квантизация KV cache меняет хранение, а reuse — аллокацию

KV cache можно квантизовать во время инференса. На каждом шаге decode для нового токена создаются K- и V-activation-тензоры. Модель W8A8 может уже использовать FP8 или INT8 для поддерживаемой projection-математики, но кэш остается отдельным storage-объектом.

Многие serving-стеки хранят этот объект в dtype модели или кэша. Чтобы изменить его, включите KV-cache dtype, используйте чекпоинт с cache scale или выберите реализацию квантизованного кэша.

При включенной квантизации KV cache engine записывает записи как представление меньшей точности плюс scale. При последующем attention кэш либо деквантизуется внутри ядра, либо на некоторых бэкендах часть операции attention выполняется в квантизованном домене.

Стабильная документация Quantized KV Cache в vLLM напрямую предоставляет эту настройку через kv_cache_dtype="fp8" или --kv-cache-dtype fp8. vLLM поддерживает форматы кэша FP8 E4M3 и E5M2, а также стратегии scale per-tensor и per-attention-head. Можно использовать scale по умолчанию или калибровку по датасету через llm-compressor. С FlashAttention 3 vLLM также может выполнять операции attention в домене FP8, квантизуя query в дополнение к key и value.

TensorRT-LLM предоставляет FP8 KV cache через KvCacheConfig(dtype='fp8') и перечисляет FP8 KV cache и NVFP4 KV cache как отдельные quantization recipes, отличные от квантизации весов и активаций. В Hugging Face Transformers также есть путь QuantizedCache через cache_implementation="quantized": hqq поддерживает форматы кэша int2, int4 и int8, а quanto — int2 и int4.

Обычный KV caching сохраняет предыдущие keys и values, чтобы не пересчитывать их. Prefix caching повторно использует блоки кэша между запросами с одинаковым префиксом. PagedAttention уменьшает фрагментацию и улучшает аллокацию, а KV offload перемещает блоки кэша между уровнями памяти. Совместимость этих комбинаций зависит от рантайма. QuantizedCache в Hugging Face не поддерживает offloading. vLLM документирует квантизованный KV cache отдельно от prefix caching и других функций управления кэшем. Проверяйте каждую комбинацию в рантайме, который будете деплоить.

Риск для качества здесь отличается от weight-only PTQ. Квантизация KV cache вносит ошибку в состояние attention, считываемое на каждом последующем шаге decode. Отдельно тестируйте retrieval в длинном контексте, поведение в многоходовых диалогах, безопасность и отказы, форматирование tool use и латентность вывода. KVQuant, KIVI и исследование FP8 KV cache в vLLM рассматривают квантизацию KV cache как отдельную задачу.

Размер модели и длина контекста сами по себе не определяют, превзойдет ли сжатие кэша еще один раунд сжатия весов. Вычислите байты кэша по приведенному выше уравнению, используя число KV heads модели, размерность head, активный batch и dtype кэша. Затем сравните результат с объемом памяти, сэкономленным при переходе между двумя конкретными форматами весов, например BF16 и INT4. Если кэш больше, тестирование квантизации KV cache в FP8 может освободить больше serving-памяти, чем дальнейшее уменьшение весов.


7. Железо сужает выбор

Footprint весов легко оценить по числу параметров и точности хранения — тот же подход к sizing используется в обсуждениях serving-памяти вокруг KV cache:

Weight Size (GB)Parameter Count (B)×Bits8\text{Weight Size (GB)} \approx \frac{\text{Parameter Count (B)} \times \text{Bits}}{8}
Размер моделиВеса BF16Веса FP8 / INT8Веса INT4
7B / 8B~14–16 GB~7–8 GB~3,5–4 GB
14B~28 GB~14 GB~7 GB
32B / 34B~64–68 GB~32–34 GB~16–17 GB
70B~140 GB~70 GB~35 GB
109B MoE~218 GB всего~109 GB~55 GB

MoE-модели могут активировать меньше параметров на токен, но полный набор весов все равно должен где-то находиться, если только рантайм не поддерживает offload. Матрица поддержки квантизации TensorRT-LLM рассматривает семейства MoE-моделей как отдельные deployment targets со своими поддерживаемыми рецептами.

Железо деплоя ограничивает жизнеспособные форматы квантизации:

  • Сервинг на CPU зависит от vector instructions, таких как AVX-512 или AMX. Файл GGUF, загружаемый через llama.cpp, — практичный вариант.
  • Apple Silicon использует unified memory, поэтому локальные модели могут занимать большой общий пул RAM вместо выделенной VRAM. GGUF и llama.cpp остаются распространенным путем для локального рантайма, поскольку GGUF создан для GGML-экзекьюторов.
  • NVIDIA Ampere поддерживает serving-пути с INT8 tensor cores, но не нативную FP8 W8A8-математику на tensor cores. Распространенные варианты — weight-only квантизация W4A16 или статичный INT8, что соответствует матрице поддержки железа TensorRT-LLM.
  • NVIDIA Ada и Hopper поддерживают FP8-serving в TensorRT-LLM. FP8 W8A8-serving стоит протестировать на этих GPU.
  • NVIDIA Blackwell добавляет поддержку NVFP4 и microscaling, но программный путь по-прежнему важен. Считайте ранние стеки floating point низкой разрядности чувствительными к версии.

8. Калибровка и оценка перед деплоем

Модель, которая загрузилась, прошла smoke test. Для деплоя нужны проверки качества и сервинга на целевом workload. Современные оценки квантизации показывают разные результаты для сервинга LLM, задач с длинным контекстом и моделей с тяжелым ризонингом.

Проверки калибровки и оценки квантизованных моделейПроверки калибровки и оценки квантизованных моделей

Для калибровки используйте промпты, похожие на production-трафик:

  • Включайте RAG-трейсы, SQL-запросы, истории агентов, кодинговые задачи, payload tool call и системные промпты из целевого workload. Static PTQ зависит от соответствия калибровочных данных production-распределению.
  • Сопоставляйте длины последовательностей. Короткие одноповоротные промпты не проявят поведение активаций в длинном контексте.
  • Оставляйте embed_tokens и lm_head в формате более высокой точности, если это позволяет метод или runtime; это распространенный паттерн исключения в рецептах LLM Compressor.
  • Используйте достаточно примеров, чтобы стабилизировать диапазоны активаций. В примере KV cache для vLLM задано NUM_CALIB_SAMPLES = 512. Считайте это одним документированным примером, а не универсальным числом. Подходящее количество примеров зависит от метода, модели, длины последовательности и production-workload.
  • Перед использованием production-логов удаляйте секреты и приватные пользовательские данные.

При оценке проверяйте и языковое качество, и поведение сервинга:

  • Perplexity на стандартном корпусе выявляет общую деградацию языка, но бенчмарк JarvisLabs напоминает, что perplexity и throughput могут изменяться независимо.
  • Доменные задачи выявляют сбои, которые скрывает perplexity. Используйте HumanEval для кодинга, MMLU для общих знаний и AIME или MATH-500 для математического ризонинга, если эти домены важны.
  • Для агентных систем важны проверки формата. Тестируйте соответствие JSON Schema, markdown-вывод, форму tool call и поведение отказа, поскольку оценки квантизованных моделей могут не заметить application-level сбои, даже когда агрегатная точность на бенчмарке остается стабильной.
  • Тесты длинного контекста выявляют ущерб от квантизации KV cache. Needle-in-a-haystack — грубый тест, но результаты квантизации на длинном контексте показывают, почему такие проверки должны входить в deploy gate.
  • В load tests нужно отчитываться о throughput, TTFT, межтокенной латентности, максимальной емкости batch и пиковой памяти. vLLM предоставляет эти измерения через vllm bench serve.

Модели с тяжелым ризонингом оценивайте особенно тщательно. Квантизация sub-4-bit или W4A4 без rotations может ухудшить точность ризонинга, даже если baseline perplexity остается стабильной; это основной вывод исследования reasoning-моделей после квантизации.


9. Workflow companion-репозитория

Companion-репозиторий slavadubrov/model-compression-demo предназначен для воспроизводимости процесса принятия решений. Он использует uv и фокусируется на планировании, рецептах, dry run и конфигурациях бенчмарков, основанных на тех же источниках, что и эта статья: vLLM, LLM Compressor, TensorRT-LLM и статьях об алгоритмах.

Публичный README на ревизии 8b45003849e830bed2ff341a9f027b017d932c1f проверен 16.08.2026. Companion checkout отсутствует в этом workspace, поэтому я не мог запустить его CLI здесь. Приведенные ниже команды являются иллюстративными, пока вы не запустите их из этого зафиксированного checkout; кроме того, план бенчмарка по-прежнему требует целевого железа для сервинга.

Не копируйте результат FP8-рецепта из этой зафиксированной ревизии. Ее команда recipe --algorithm fp8-dynamic создает внутренне несовместимые model и output path. Команда намеренно не приведена здесь, пока companion не будет исправлен.

Склонируйте репозиторий и изучите поддерживаемые алгоритмы:

git clone https://github.com/slavadubrov/model-compression-demo.git
cd model-compression-demo
git checkout 8b45003849e830bed2ff341a9f027b017d932c1f
uv run python demo.py list-algorithms

Начните с планирования и sizing:

uv run python demo.py plan \
  --model-preset qwen3-8b \
  --goal fit-memory \
  --hardware ampere \
  --context 4096 \
  --concurrency 4

uv run python demo.py estimate \
  --model-preset qwen3-8b \
  --scheme w4a16 \
  --context 4096 \
  --concurrency 4

uv run python demo.py plan \
  --model-preset qwen3-0.6b \
  --hardware cpu

Затем сгенерируйте рецепт и выполните preview квантизации, прежде чем тратить время GPU:

uv run python demo.py recipe --algorithm gptq-w4a16

uv run python demo.py quantize --dry-run
uv run python demo.py quantize \
  --algorithm gptq-w4a16 \
  --model Qwen/Qwen3-8B \
  --dry-run

Для планирования сервинга и бенчмарков:

uv run python demo.py serve-command \
  --algorithm fp8-dynamic \
  --fp8-kv-cache \
  --enable-prefix-caching

uv run python demo.py benchmark-plan \
  --model Qwen/Qwen3-8B \
  --algorithms gptq-w4a16,rtn-w8a16,fp8-dynamic \
  --dataset-name sharegpt \
  --num-prompts 200 \
  --input-len 1024 \
  --output-len 256 \
  --output-json reports/quantization-benchmark-plan.json

Наконец, сравните базовую и сжатую модели с явными порогами:

uv run python demo.py quality-eval \
  --base-model Qwen/Qwen3-8B \
  --compressed-model outputs/Qwen3-8B-W4A16 \
  --mode all \
  --lm-eval-task hellaswag \
  --lm-eval-limit 50 \
  --max-perplexity-delta-pct 5 \
  --output-json reports/qwen3-8b-w4a16-quality.json

Выполняйте работу по порядку: спланируйте целевой вариант, оцените память, выполните dry run рецепта, проведите бенчмарк сервинга, затем сравните качество с порогами. Эта последовательность отражает разделение, описанное в статье между оценкой памяти, бенчмаркингом рантайма и оценкой качества.


10. Для diffusion-моделей нужен отдельный путь

Diffusion- и diffusion-transformer-пайплайны имеют другое поведение активаций, чем авторегрессионные LLM. SVDQuant рассматривает квантизацию diffusion как отдельную задачу, связанную с activation-выбросами.

Авторегрессионные LLM генерируют по одному токену за раз. Diffusion-модели выполняют повторяющиеся шаги денойзинга, и распределения их активаций меняются в процессе. Стандартный 4-битный проход квантизации для LLM может уменьшить память diffusion-модели, но при этом создать сильные визуальные артефакты. Специализированные для diffusion методы, такие как SVDQuant / Nunchaku и квантизация diffusion в NVIDIA ModelOpt, учитывают это иное поведение активаций.

Используйте следующие консервативные эвристики, а не универсальные настройки по умолчанию. Каждый пайплайн, компонент, модель и runtime требуют отдельных тестов:

  1. На первом сравнении оставьте VAE в 16-битном формате. Эта консервативная эвристика уменьшает один из источников артефактов изображений. Переходите к меньшей точности только после валидации метода и целевого пайплайна.
  2. Сначала попробуйте DiT или U-Net backbone, поскольку на него часто приходится наибольшая доля параметров. Это эвристика, поэтому проверьте память, латентность и качество изображений для целевого пайплайна. Методы квантизации diffusion используют такой же покомпонентный подход.
  3. Обрабатывайте text encoders отдельно. Квантизация T5-XXL или CLIP может повлиять на соответствие промпту или рендеринг текста в конкретном пайплайне, поэтому оценивайте их независимо, не предполагая поведения обычного трансформера.
  4. Используйте diffusion-aware методы, такие как SVDQuant, когда основной проблемой являются activation-выбросы.
  5. Оценивайте результат по изображениям, а не по текстовым метрикам. Проверяйте соответствие промпту, рендеринг текста, оттенки кожи, цветовой баланс, мелкие детали, латентность и VRAM.

Если в evaluation set есть только простые или распространенные промпты, вы пропустите edge-case-сбои. Добавляйте сложные случаи: мелкий текст, руки, повторяющиеся объекты, структурированные макеты и промпты с negative constraints, поскольку сбои квантизации diffusion проявляются визуально, а не в perplexity языковой модели.


11. Production-настройки по умолчанию

Для enterprise-сервинга LLM начните с baseline BF16 в том же serving engine, который планируете использовать. Если цель — throughput и железо это поддерживает, протестируйте FP8 W8A8. Если модель не помещается, протестируйте AWQ или GPTQ W4A16 с ядрами класса Marlin. Если проблема в длинном контексте или конкурентности, протестируйте квантизацию KV cache в FP8. Если проблема в повторяющихся префиксах, дополнительно включите prefix caching. Выпускайте сжатую версию только после прохождения и quality-, и serving-бенчмарков.

Для локального и edge-инференса начните с файла GGUF, используя Q4_K_M или Q5_K_M. Если память позволяет и качество важнее footprint, переходите на Q8_0 GGUF. Переход ниже 4 бит — крайняя мера, а не вариант по умолчанию.

Для файн-тюнинга используйте NF4 с QLoRA, чтобы дешево обучать адаптеры. Оцените адаптер в приложении до объединения. После объединения экспортируйте его в реально нужный serving-артефакт: совместимый с llama.cpp файл GGUF, AWQ/GPTQ/compressed-tensors-чекпоинт, FP8-serving-чекпоинт или BF16.

Для diffusion начните с этих консервативных эвристик и визуально протестируйте каждую комбинацию пайплайна, модели и рантайма. Текстовая perplexity не покажет, сломался ли image-пайплайн, поэтому используйте diffusion-специфичные свидетельства, такие как SVDQuant, и визуальную оценку.


References

  • JarvisLabs vLLM Benchmarks: JarvisLabs, vLLM Quantization Complete Guide and Benchmarks, 2026. JarvisLabs.
  • Hugging Face Optimum Quantization Guide: Hugging Face, Quantization conceptual guide. Docs.
  • vLLM Quantization Docs: проект vLLM, Quantization. Docs.
  • vLLM Quantized KV Cache Docs: проект vLLM, Quantized KV Cache. Docs.
  • vLLM Benchmark Docs: проект vLLM, vllm bench serve. Docs.
  • LLM Compressor Docs: проект vLLM, LLM Compressor. Docs.
  • GPTQModel: ModelCloud, GPTQModel. GitHub.
  • TensorRT-LLM Quantization: NVIDIA, TensorRT-LLM Quantization. Docs.
  • NVIDIA NVFP4: NVIDIA, Introducing NVFP4 for Efficient and Accurate Low-Precision Inference. Blog.
  • Hugging Face QuantizedCache: Hugging Face, Cache strategies: Quantized cache. Docs.
  • NVIDIA Model Optimizer: NVIDIA, Model Optimizer. GitHub.
  • torchao Quantization: PyTorch, torchao quantization overview. Docs.
  • bitsandbytes Quantization: Hugging Face, bitsandbytes. Docs.
  • HQQ: Dropbox, Half-Quadratic Quantization. GitHub.
  • PEFT: Hugging Face, Parameter-Efficient Fine-Tuning. Docs.
  • Ollama: локальный runtime-моделей Ollama. Website.
  • LM Studio: локальный AI-runtime LM Studio. Website.
  • AutoGPTQ status: репозиторий AutoGPTQ, архивирован в апреле 2025 года. GitHub.
  • AutoAWQ status: репозиторий AutoAWQ, архивирован и deprecated в мае 2025 года. GitHub.
  • GPTQ: Frantar et al., GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers, NeurIPS 2023. arXiv:2210.17323.
  • Marlin: Frantar et al., MARLIN: Mixed-Precision Auto-Regressive Parallel Inference on Large Language Models, arXiv:2408.11743. arXiv:2408.11743.
  • AWQ: Lin et al., AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration, MLSys 2024. arXiv:2306.00978.
  • SmoothQuant: Xiao et al., SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models, ICML 2023. arXiv:2211.10438.
  • QuaRot: Ashkboos et al., QuaRot: Outlier-Free 4-Bit Inference in Rotated LLMs, NeurIPS 2024. arXiv:2404.00456.
  • SpinQuant: Meta AI Research, SpinQuant: LLM Quantization with Learned Rotations, arXiv:2405.16406. arXiv:2405.16406.
  • QLoRA / NF4: Dettmers et al., QLoRA: Efficient Finetuning of Quantized LLMs, NeurIPS 2023. arXiv:2305.14314.
  • SVDQuant / Nunchaku: MIT HAN Lab, SVDQuant: Absorbing Outliers by Low-Rank Components for 4-Bit Diffusion Models, ICLR 2025. arXiv:2411.05007, Nunchaku.
  • vLLM PagedAttention: Kwon et al., Efficient Memory Management for Large Language Model Serving with PagedAttention, SOSP 2023. arXiv:2309.06180.
  • Grouped-Query Attention: Ainslie et al., GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints, EMNLP 2023. arXiv:2305.13245.
  • vLLM FP8 KV Cache: Kubler, Kurtic, Wilkinson et al., The State of FP8 KV-Cache and Attention Quantization in vLLM, vLLM Blog, April 2026. vLLM Blog.
  • KIVI: Liu et al., KIVI: A Tuning-Free Asymmetric 2bit Quantization for KV Cache, ICML 2024. arXiv:2402.02750.
  • KVQuant: Hooper et al., KVQuant: Towards 10 Million Context Length LLM Inference with KV Cache Quantization, NeurIPS 2024. arXiv:2401.18079.
  • LLM Serving Evaluation: Kurtic et al., “Give Me BF16 or Give Me Death”? Accuracy-Performance Trade-Offs in LLM Quantization, ACL 2025. arXiv:2411.02355.
  • Long-context Quantization Evaluation: Mekala et al., Does quantization affect models’ performance on long-context tasks?, arXiv:2505.20276. arXiv:2505.20276.
  • Reasoning Evaluation: Quantization Hurts Reasoning? An Empirical Study on Quantized Reasoning Models, arXiv:2504.04823. arXiv:2504.04823.
  • SlideSparse: SlideSparse: Fast and Flexible (2N-2):2N Structured Sparsity, arXiv:2603.05232v1. arXiv:2603.05232v1.
  • HumanEval: OpenAI, HumanEval. GitHub.
  • MMLU: Hendrycks et al., Measuring Massive Multitask Language Understanding. arXiv:2009.03300.
  • MATH-500: Hugging Face H4, MATH-500. Dataset.
  • GGUF and llama.cpp: ggml-org, GGUF file format и llama.cpp. GGUF, llama.cpp.
  • Hugging Face GGUF Docs: Hugging Face, GGUF. Docs.
  • Reference Repository: slavadubrov/model-compression-demo.