Guia de Quantização de Modelos: Dos Fundamentos ao Serving em Produção

Tradução automática Este artigo foi traduzido automaticamente a partir da versão original em inglês.

A quantização utiliza menos bits para representar os valores de um modelo. Um caminho de serving pode quantizar pesos, ativações, a cache KV ou uma combinação destes, e cada alvo resolve um problema diferente de serving.

Escolha o alvo com base no bottleneck atual: memória dos pesos, computação das ativações, tamanho da cache KV, kernels, hardware, dados de calibração ou qualidade. Um modelo de 4 bits pode caber na VRAM e, ainda assim, executar lentamente com um kernel não otimizado, como demonstra o benchmark do vLLM da JarvisLabs. FP8 funciona bem em hardware NVIDIA Hopper com um runtime compatível, mas não oferece qualquer benefício nativo em GPUs não suportadas. A matriz de hardware do TensorRT-LLM mostra os caminhos suportados. Para contextos longos ou elevada concorrência, a quantização da cache KV pode poupar mais memória do que a quantização dos pesos.

Se é engenheiro de ML ou de plataforma e está a escolher um caminho de quantização para um modelo que precisa de servir, este guia é para si. No final, deverá conseguir associar um bottleneck a um formato candidato, a um runtime e a um plano de validação antes da implementação.

Para uma comparação breve entre artefactos e métodos, consulte Formatos de Quantização de LLM.

Como utilizar este guia de quantização


1. Comece pelo bottleneck

Identifique o que limita a carga de trabalho antes de escolher a largura em bits. A resposta pode ser a memória dos pesos do modelo, a computação de prefill, a largura de banda do decode ou a cache KV, e não a precisão numérica por si só.

Bottlenecks comuns e respetivos pontos de partida:

Se este for o problemaComece por aquiFerramentas típicasVerifique antes da implementação
Os pesos do modelo não cabem na VRAMQuantização exclusivamente dos pesos W4A16AWQ ou GPTQ com llm-compressor ou GPTQModelPerplexidade, geração de código, raciocínio, seguimento de instruções
O serving de elevado débito está limitado pelo computeFP8 ou INT8 W8A8PTQ em FP8, SmoothQuant, TensorRT-LLM, vLLMDébito, TTFT, precisão da tarefa
O contexto longo ou a elevada concorrência preenche a GPUQuantização da KV-cachevLLM, TensorRT-LLM ou Transformers QuantizedCacheRecuperação em contextos longos, latência, segurança e qualidade
Inferência local em CPU, Apple Silicon ou desktopFicheiros GGUF com codificações locais de tensoresllama.cpp, Ollama, LM StudioLatência do prompt, utilização de RAM, codificação de tensor selecionada e qualidade subjetiva da saída
O fine-tuning com adapters tem de caber numa única GPUNF4 / QLoRAbitsandbytes, peftLoss de fine-tuning e qualidade do modelo após merge
O pipeline de geração de imagens é demasiado grande ou lentoINT4 ou FP8 específicos para difusãoSVDQuant, Nunchaku, torchao, NVIDIA ModelOptArtefactos visuais, alinhamento com o prompt, latência, VRAM

Use esta tabela como mapa. As secções abaixo explicam por que razão esses pontos de partida são diferentes.

Notação usada nas receitas de serving

  • W{x}A{y} indica a precisão usada no cálculo suportado para pesos e activações, normalmente nos caminhos GEMM dos motores de serving. W4A16 armazena os pesos em formato de 4 bits e mantém as activações com precisão de 16 bits. W8A8 usa pesos e activações de 8 bits nos caminhos de computação suportados, mas não define automaticamente o dtype de armazenamento persistente de todos os tensores do runtime.
  • FP8, INT8, INT4, NF4 são formatos numéricos. Determinam os valores que podem ser representados.
  • GPTQ, AWQ, SmoothQuant, QuaRot são algoritmos. Determinam como mapear um modelo treinado para um formato de menor precisão.
  • GGUF é um formato de ficheiro que armazena tensores e metadados para runtimes baseados em GGML e llama.cpp. Um ficheiro GGUF pode conter tipos de tensor não quantizados, como F16, BF16 ou F32, bem como representações quantizadas. Entre os presets incluem-se Q4_K_M, Q5_K_M, Q8_0, IQ*, TQ* e MXFP4. A representação do tensor determina a escolha de quantização. Por si só, GGUF não descreve uma receita de serving CUDA-style FP8 W8A8.
  • KV cache é a cache de atenção usada durante a geração. Armazena as keys e values anteriores para que o modelo não tenha de recalcular toda a conversa a cada token.
  • KV-cache quantization armazena os tensores de activação key/value em formato de cache de menor precisão, como FP8, INT8, INT4 ou INT2, consoante o suporte do runtime. Isto é diferente de prefix caching, PagedAttention ou offload, que determinam se as entradas da cache são reutilizadas, como são alocadas ou onde residem.
  • GEMM significa multiplicação geral de matrizes. A maior parte do tempo de inferência dos transformers é passada a efectuar multiplicações de matrizes.

2. A quantização é arredondamento controlado

A quantização mapeia valores de alta precisão para um conjunto menor de valores representáveis, que é a definição fundamental usada tanto pelo Hugging Face Optimum como pelo TensorRT-LLM. Poupa memória e largura de banda. Também introduz erro de arredondamento.

O INT4 disponibiliza apenas 16 valores discretos, pelo que mapear pesos BF16 para essa grelha cria erro de arredondamento. Métodos como GPTQ, AWQ e SVDQuant procuram preservar outliers e reduzir o erro de reconstrução. Um bom mapeamento poupa memória com pouca perda de qualidade. Um mau mapeamento prejudica o raciocínio, o seguimento de instruções ou a fidelidade visual.

Mapeamento simétrico e assimétrico

Seguindo o mapeamento afim usado em guias de quantização comuns, a quantização mapeia um valor float contínuo x[β,α]x \in [\beta, \alpha] para uma grelha discreta.

  • xx é o valor original de alta precisão.
  • xqx_q é o valor quantizado.
  • ss é a escala, ou tamanho do passo.
  • zz é o ponto zero, a posição inteira que representa 0.0.
  • [qmin,qmax][q_{\min}, q_{\max}] é o intervalo de inteiros pretendido. Os valores assinados de 4 bits usam frequentemente [7,7][-7, 7].

A quantização simétrica centra a grelha em torno de zero e define 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)

Isto é compatível com o hardware, porque os cálculos em runtime não precisam de subtrair um offset de ponto zero. A stack de quantização do PyTorch expõe estas escolhas de escala afim e ponto zero como parâmetros primitivos de quantização em torchao.

A quantização assimétrica desloca a grelha para abranger intervalos assimétricos:

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)

Esta grelha deslocada pode preservar melhor as ativações exclusivamente positivas, mas o offset acrescenta trabalho, a menos que o kernel o trate de forma eficiente.

Como a quantização mapeia valores de alta precisão para buckets de baixa precisão

A granularidade da escala é importante

O fator de escala pode abranger um tensor de pesos inteiro, um canal ou um pequeno grupo de valores. A documentação da cache KV em FP8 do vLLM usa a mesma distinção entre estratégias de escala por tensor e por cabeça de atenção. Grupos mais pequenos preservam normalmente melhor a qualidade, mas exigem mais metadados de escala.

Granularidade da escalaO que partilha uma escalaEfeito na qualidade e na execução
Por tensorToda a matriz de pesosArmazena poucos metadados, mas um outlier pode alargar a grelha e reduzir a precisão em toda a camada.
Por canalUma linha de saídaImpede que canais com intervalos estreitos partilhem o intervalo mais amplo de outro canal. Muitos caminhos de pesos de 8 bits usam esta granularidade.
Por grupoUm bloco numa linha, normalmente 64 ou 128 valoresConfina um outlier a um bloco pequeno, ao custo de mais escalas. O AutoGPTQ usa group_size=128 nos seus exemplos de GPTQ.

Os pesos são estáticos, pelo que as respetivas escalas podem ser calculadas offline antes de carregar o modelo. As ativações mudam com cada token, o que torna os seus intervalos dependentes da carga de trabalho.

Escalonamento das ativaçõesQuando o runtime escolhe a escalaVantagemModo de falha ou custo
EstáticoOffline, a partir de um dataset de calibraçãoEvita calcular a escala durante a inferência.Prompts fora do comprimento ou da distribuição calibrados podem truncar picos das ativações e degradar o output.
DinâmicoDurante cada forward passAdapta-se aos valores atuais das ativações e à mistura de prompts.Calcular os intervalos em cada camada acrescenta trabalho e requer kernels otimizados.

A KV cache situa-se entre estes dois casos. As keys e values começam por ser tensores de ativações em runtime: cada camada calcula-os a partir dos hidden states durante o forward pass. Depois de gerados, deixam de ser intermediários transitórios de matmul e passam a ser estado persistente do serving, que a atenção consulta para os tokens seguintes.

Um motor de serving pode armazenar esse estado numa precisão inferior e manter os metadados de escala associados. vLLM’s Quantized KV Cache, TensorRT-LLM’s FP8 KV Cache e Transformers QuantizedCache disponibilizam todos esta opção de armazenamento.

A precisão de armazenamento da cache continua separada da precisão das ativações utilizada nos kernels lineares. «KV-cache quantization» designa uma otimização específica da cache, não todas as técnicas que reutilizam, alocam ou movem entradas da cache.

PTQ e QAT ocorrem em fases diferentes

A quantização pós-treino, ou PTQ, comprime um modelo treinado posteriormente. O treino consciente da quantização, ou QAT, expõe o modelo ao ruído da quantização durante o treino, permitindo-lhe adaptar-se.

MétodoQuando são aprendidos os intervalosUtilize-o quandoCusto
PTQ apenas dos pesosOffline, para pesos estáticosO modelo não cabe ou o decode está limitado pela largura de bandaAs ativações continuam a ser processadas em 16-bit
PTQ estáticaOffline, a partir de prompts de calibraçãoPretende serving W8A8 rápidoOs dados de calibração têm de corresponder à produção
PTQ dinâmicaEm runtime, por batch ou caminho de ativaçõesAs distribuições de entrada variam muitoTrabalho adicional em runtime e suporte de hardware mais limitado
QATDurante o treinoA PTQ degrada a qualidade num modelo sensívelInfraestrutura completa de treino e muito mais computação

Os dados de calibração têm de ser representativos do tráfego que irá servir. Por exemplo, o caminho de calibração da KV-cache do vLLM usa um dataset selecionado através de llm-compressor. Se os prompts de produção forem traces RAG longos, parágrafos curtos da Wikipédia irão produzir métricas de benchmark convincentes e uma implementação danificada. O modelo ajustará as escalas das ativações com base em texto curto e, depois, encontrará padrões de ativação diferentes quando receber prompts reais com contexto longo. As avaliações de quantização para contexto longo medem diretamente este risco.


3. Os formatos numéricos determinam os requisitos de hardware

O formato numérico define os valores que o modelo consegue representar em memória. Para uma computação eficiente, os kernels de runtime e o hardware têm de suportar a mesma largura de bits e o mesmo formato. O TensorRT-LLM documenta tanto a lista de recipes como a matriz de suporte de hardware.

FormatoArmazenamento por valorBoa opção predefinida paraPrincipal aspeto a monitorizar
BF16 / FP162 bytesInferência de base e serving compatível com treinoElevado consumo de VRAM e tráfego elevado de largura de banda de memória
FP81 byteServing W8A8 de alto débito em Ada, Hopper e BlackwellRequer tensor cores FP8 nativos e suporte do runtime
INT81 byteServing W8A8 em hardware mais antigo ou não-NVIDIAOutliers nas ativações e sensibilidade à calibração estática
INT40,5 bytesW4A16 quando a memória ocupada pelos pesos é o principal limitePerda de qualidade em modelos mais pequenos ou orientados para raciocínio
FP4 / NVFP4~0,5 bytesExperiências da era Blackwell e primeiros caminhos de servingRequisitos específicos do compilador e do runtime do hardware
Codificações / presets GGUF do llama.cppVariávelInferência local em CPU, Apple Silicon, desktop e edgeGGUF é o contentor. A codificação do tensor é a escolha de quantização.
NF40,5 bytesTreino de adapters QLoRANormalmente, é o formato de exportação errado para serving em produção

BF16 e FP16 utilizam ambos 16 bits, mas distribuem a precisão de forma diferente e, por isso, falham de maneiras diferentes. BF16 mantém o intervalo do expoente de 8 bits do FP32 e é mais difícil de fazer entrar em overflow. FP16 tem mais bits de mantissa e um intervalo de expoente mais estreito, pelo que os picos das activaçãos exigem mais cuidado. A avaliação de Kurtic et al. utiliza explicitamente BF16 como baseline ao comparar formatos de serving FP8, INT8 e INT4.

O FP8 tem duas variantes comuns. E4M3 oferece mais precisão e é normalmente utilizado para pesos e activaçãos no forward pass. E5M2 oferece um maior dynamic range e é mais útil para gradientes ou caminhos de activação voláteis. O vLLM disponibiliza os dois dtypes de KV cache FP8 E4M3 e E5M2. No estudo ACL 2025 de Kurtic et al., “Give Me BF16 or Give Me Death”, FP8 W8A8 foi efectivamente lossless na família Llama-3.1, em mais de 500 000 avaliações. O resultado abrange essa família de modelos, essa suite de avaliação e essa configuração de serving. Cada deployment continua a precisar do seu próprio quality gate.

O Blackwell introduz formatos de microscaling, como MXFP8 e NVFP4. Em vez de uma escala para um tensor ou linha inteira, o microscaling utiliza blocos muito pequenos. O explicador da NVIDIA sobre NVFP4 descreve valores de floating point de 4 bits em blocos de 16, com factores de escala FP8 e uma escala FP32 de nível superior. Esta abordagem procura oferecer uma footprint próxima de INT4, mantendo o comportamento de floating point. No entanto, requer uma arquitectura de hardware, um compilador e suporte de runtime compatíveis, razão pela qual o TensorRT-LLM indica o suporte para FP4 e FP8 por geração de GPU.


4. Quantização apenas de pesos vs. quantização de pesos e activaçãos

A notação WxAy descreve a precisão dos pesos e das activaçãos, que colocam diferentes tipos de pressão sobre a GPU durante a inferência.

Mecânica da quantização: apenas pesos vs. pesos e activaçãos

Durante o prefill, o modelo processa o prompt de entrada. Esta fase é normalmente compute-bound, porque a GPU executa grandes multiplicações de matrizes, razão pela qual as receitas W8A8 FP8/INT8 são importantes para serving orientado ao throughput.

Durante o decode, o modelo gera um token de cada vez. Esta fase é frequentemente memory-bandwidth-bound, porque a GPU continua a carregar pesos da VRAM para produzir o token seguinte. Artigos sobre quantização apenas de pesos, como GPTQ e AWQ, procuram reduzir essa pressão diminuindo o número de bytes dos pesos.

W4A16 comprime os pesos e mantém as activaçãos em BF16 ou FP16. A GPU carrega menos bytes de pesos e, em seguida, faz dequantize dos pesos para uma representação de maior precisão antes da multiplicação. Isto ajuda no decode e nos problemas de fit-to-memory. O prefill compute-bound pode obter poucos benefícios, porque a matemática das matrizes continua a ser executada em 16 bits.

W8A8 comprime os pesos e os tensores de activação utilizados pelos kernels de matmul suportados. Se o hardware tiver tensor cores nativos de baixa precisão, o serving engine pode executar directamente a matemática das matrizes em FP8 ou INT8. Assim, o FP8 pode ajudar no serving de elevado throughput, reduzindo o tráfego de memória e utilizando aritmética mais rápida. O KV cache tem a sua própria definição de armazenamento; por isso, verifique separadamente o cache dtype ou a cache implementation do runtime.

Se o modelo couber apenas por pouco na VRAM, comece por quantização apenas dos pesos para reduzir a utilização de memória. Se o modelo couber, mas tiver dificuldades de throughput com cargas de batch elevadas, avalie FP8 ou INT8 W8A8 para acelerar a fase de computação. Se os problemas de memória só surgirem durante conversas longas, estime primeiro o termo da cache KV. Teste a quantização da cache KV quando esse termo for dominante. Ative o caching de prefixos quando os prefixos repetidos forem predominantes.


5. Algoritmos vs. kernels de runtime

Os algoritmos de quantização (como GPTQ ou AWQ) definem a forma como os pesos do modelo são mapeados para uma precisão inferior. Os kernels de runtime (como Marlin ou kernels personalizados do vLLM) são o código de baixo nível para GPU que executa a multiplicação de matrizes. Um modelo altamente comprimido só será executado rapidamente se existir um kernel otimizado para o seu formato de quantização específico.

O algoritmo de quantização e o kernel de runtime influenciam ambos os resultados do serving

O benchmark do vLLM da JarvisLabs no Qwen2.5-32B-Instruct com uma NVIDIA H200 torna visível o efeito do kernel:

Quantização / kernelPerplexidade, quanto menor melhorPass@1, quanto maior melhorThroughputTTFT
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

Não transponha estes valores diretamente para a sua stack. Resultam de um único modelo, de uma classe de GPU e de uma configuração de software. Demonstram um ponto mais específico: o nome do algoritmo no checkpoint não indica a velocidade do serving.

Por exemplo, AWQ e Marlin-AWQ utilizam os mesmos pesos de 4 bits. A implementação Marlin é muito mais rápida porque o seu kernel CUDA funde a desquantização e a multiplicação de matrizes numa única operação de GPU altamente otimizada.

Faça o benchmark do baseline e das variantes comprimidas com a mesma mistura de prompts e a mesma ferramenta, como vllm bench serve:

vllm bench serve \
  --model ./outputs/Qwen2.5-32B-Instruct-AWQ-W4A16 \
  --dataset-name sharegpt \
  --num-prompts 200 \
  --input-len 1024 \
  --output-len 256

Acompanhe o throughput, o TTFT, a latência entre tokens, a utilização de memória e a qualidade das tarefas. Quando alguns destes indicadores evoluem em sentidos opostos, é esse trade-off que precisa de observar antes de colocar o sistema em produção.

O menu de algoritmos

Use esta tabela como um mapa, não como um ranking:

AlgoritmoFormato comumO que tenta preservarPrincipal custo
GPTQW4A16Reconstrução por camada com estimativas da HessianaCalibração lenta e processamento mais complexo
AWQW4A16 / W4A8Canais de activação importantesRequer calibração e kernels de serving fundidos
SmoothQuantW8A8Comportamento das activações em INT8, transferindo a escala dos outliers para os pesosAjuste da escala por modelo
QuaRot / SpinQuantW4A4 / W4A8Menor impacto dos outliers das activações através de rotaçõesComplexidade das rotações em runtime
HQQW4A16 / W2A16Compressão rápida apenas dos pesos, sem calibraçãoA qualidade requer validações downstream com larguras de bits muito baixas
QLoRA (NF4)NF4Memória para o treino de adaptersNão é uma boa opção predefinida para serving
llama.cpp GGUF K-quants / IQ-quantsCodificações de tensores mixed low-bitQualidade da inferência local por byteNão foi concebido para serving em batch na cloud

A toolchain está a evoluir activamente. O AutoGPTQ foi arquivado em abril de 2025, e o AutoAWQ foi arquivado e oficialmente descontinuado em maio de 2025. Para novos checkpoints compressed-tensors consumidos pelo vLLM, comece pelo llm-compressor. Use o GPTQModel quando precisar do caminho GPTQ activo com Marlin, Machete, opções de memória para MoE ou offload para disco.

A pruning e a distillation também reduzem o custo de serving através de workflows distintos. A esparsidade estruturada 2:4 remove pesos segundo um padrão que os tensor cores esparsos da NVIDIA conseguem utilizar. A distillation treina um modelo student mais pequeno para imitar um modelo maior, o que pode funcionar bem em tarefas específicas. Inclua qualquer uma destas abordagens na shortlist apenas quando o projecto puder suportar o trabalho adicional de pruning ou treino.


6. Servir memória é mais do que pesos

O checkpoint comprimido é apenas uma parte da memória necessária para servir o modelo. Dimensione o runtime completo antes de decidir se a quantização dos pesos é suficiente. O PagedAttention identifica a KV cache como um dos principais componentes da memória de 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}

A quantização offline pode ser limitada por camada. Ferramentas como llm-compressor podem carregar um bloco do transformer, executar a calibração e os cálculos de quantização, gravar o bloco comprimido e avançar para o seguinte. Assim, o pico de memória da GPU fica mais próximo do tamanho da maior camada ativa, acrescido dos buffers de calibração. Continua a ser necessária RAM da CPU e espaço em disco para o checkpoint de origem, mas a GPU nem sempre tem de manter o modelo BF16 completo.

O pico de memória da GPU durante a quantização offline pode aproximar-se mais do seguinte:

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

O serving é mais exigente. O checkpoint comprimido completo tem de permanecer residente, juntamente com a KV cache e os buffers do runtime. A KV cache cresce com o comprimento do contexto e o tamanho do batch ativo:

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}

Onde:

  • LL é o número de camadas.
  • HkvH_{\text{kv}} é o número de cabeças de atenção key-value. A grouped-query attention reduz este valor ao permitir que várias cabeças de query partilhem menos cabeças KV.
  • DD é a dimensão de cada cabeça, frequentemente 128 ou 256.
  • SctxS_{\text{ctx}} é o número de tokens do prompt mais o número de tokens gerados.
  • BbatchB_{\text{batch}} é o batch ativo no serving.
  • BytesPerValue\text{BytesPerValue} é 2 para BF16 ou FP16 e 1 para FP8 ou INT8. O modo de KV cache FP8 do vLLM é o exemplo de serving stack usado neste artigo.

A quantização da KV cache altera o armazenamento, enquanto a reutilização altera a alocação

A KV cache pode ser quantizada durante a inferência. Cada passo de decode produz tensores de ativação K e V para o novo token. Um modelo W8A8 pode já usar FP8 ou INT8 nos cálculos de projeção suportados, mas a cache continua a ser um objeto de armazenamento separado.

Muitas serving stacks mantêm esse objeto no dtype do modelo ou da cache. Para o alterar, ative um dtype da KV cache, use um checkpoint com escalas da cache ou escolha uma implementação de cache quantizada.

Quando a quantização da KV cache está ativada, o motor grava as entradas numa representação de menor precisão, acompanhada pelas respetivas escalas. Mais tarde, a atenção desquantiza a cache dentro do seu kernel ou, em alguns backends, executa parte da operação de atenção no domínio quantizado.

A documentação estável da Quantized KV Cache do vLLM expõe diretamente esta funcionalidade através de kv_cache_dtype="fp8" ou --kv-cache-dtype fp8. O vLLM suporta os formatos de cache FP8 E4M3 e E5M2, além de estratégias de escala por tensor e por cabeça de atenção. Disponibiliza três formas de obter as escalas: valores predefinidos, estimativa durante o warmup e calibração com um dataset através de llm-compressor. Com o FlashAttention 3, o vLLM também pode executar operações de atenção no domínio FP8, quantizando as queries além das keys e values.

TensorRT-LLM disponibiliza a cache KV em FP8 através de KvCacheConfig(dtype='fp8') e apresenta a cache KV em FP8 e a cache KV em NVFP4 como receitas de quantização distintas da quantização de pesos/ativações. O Hugging Face Transformers também disponibiliza um caminho QuantizedCache através de cache_implementation="quantized", com hqq a suportar formatos de cache int2, int4 e int8 e quanto a suportar int2 e int4.

A cache KV normal armazena as chaves e os valores anteriores para evitar recalculá-los. O caching de prefixos reutiliza blocos de cache entre pedidos com o mesmo prefixo. O PagedAttention reduz a fragmentação e melhora a alocação, enquanto o offload da cache KV move blocos de cache entre níveis de memória. Estas combinações dependem do runtime. O QuantizedCache do Hugging Face não suporta offloading. O vLLM documenta a cache KV quantizada separadamente do caching de prefixos e de outras funcionalidades de gestão da cache. Valide cada combinação no runtime que vai utilizar em produção.

O risco para a qualidade também difere do PTQ exclusivamente de pesos. A quantização da cache KV introduz erro no estado de atenção lido em cada passo de decoding subsequente. Teste separadamente a recuperação em contextos longos, o comportamento em múltiplos turnos, a segurança e as recusas, a formatação do uso de ferramentas e a latência de geração. O KVQuant, o KIVI e o estudo sobre a cache KV em FP8 do vLLM avaliam a quantização da cache KV como um problema autónomo.

O tamanho do modelo e o comprimento do contexto, por si só, não determinam se a compressão da cache é mais vantajosa do que uma nova ronda de compressão dos pesos. Calcule os bytes da cache utilizando a equação acima, com o número de cabeças KV do modelo, a dimensão das cabeças, o batch ativo e o dtype da cache. Em seguida, compare esse resultado com os bytes poupados entre dois formatos de pesos identificados, como BF16 e INT4. Se a cache for maior, testar a quantização da cache KV em FP8 poderá libertar mais memória de serving do que voltar a reduzir os pesos.


7. O hardware reduz as opções

A ocupação dos pesos é fácil de estimar a partir do número de parâmetros e da precisão de armazenamento, seguindo a mesma lógica de dimensionamento utilizada nas discussões sobre memória de serving para a cache KV:

Weight Size (GB)Parameter Count (B)×Bits8\text{Weight Size (GB)} \approx \frac{\text{Parameter Count (B)} \times \text{Bits}}{8}
Tamanho do modeloPesos BF16Pesos FP8 / INT8Pesos 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 total~109 GB~55 GB

Os modelos mixture-of-experts podem ativar menos parâmetros por token, mas o conjunto completo de pesos continua a ter de estar residente algures, a menos que o runtime suporte offload. A matriz de suporte à quantização do TensorRT-LLM trata as famílias de modelos MoE como alvos de deployment com receitas suportadas próprias.

O hardware de deployment restringe os formatos de quantização viáveis:

  • CPU serving depende de instruções vetoriais como AVX-512 ou AMX. Carregar um ficheiro GGUF através de llama.cpp é a opção prática.
  • Apple Silicon utiliza memória unificada, pelo que os modelos locais podem usar um grande conjunto de RAM partilhada em vez de VRAM dedicada. GGUF e llama.cpp continuam a ser o caminho habitual para runtimes locais, porque o GGUF foi concebido para executores GGML.
  • NVIDIA Ampere suporta caminhos de serving com tensor cores INT8, mas não operações nativas FP8 W8A8 com tensor cores. As opções habituais são a quantização weight-only W4A16 ou INT8 estático, de acordo com a matriz de suporte de hardware do TensorRT-LLM.
  • NVIDIA Ada e Hopper suportam caminhos de serving FP8 no TensorRT-LLM. Vale a pena testar serving FP8 W8A8 nestas GPUs.
  • NVIDIA Blackwell acrescenta suporte para NVFP4 e microscaling, mas o caminho de software continua a ser importante. Considere as primeiras stacks de floating point de baixa precisão sensíveis à versão.

8. Calibração e avaliação antes do deploy

Um modelo que é carregado passou um smoke test. O deploy exige verificações de qualidade e de serving para a workload-alvo. Avaliações recentes de quantização reportam resultados diferentes para serving de LLMs, tarefas com contexto longo e modelos com forte componente de raciocínio.

Verificações de calibração e avaliação para modelos quantizados

Para a calibração, utilize prompts semelhantes aos de produção:

  • Inclua traces de RAG, queries SQL, históricos de agentes, tarefas de código, payloads de tool calls e system prompts da workload-alvo. A PTQ estática depende de os dados de calibração corresponderem à distribuição de produção.
  • Faça corresponder os comprimentos das sequências. Prompts curtos de uma só interação não revelam o comportamento das ativações em contextos longos.
  • Mantenha embed_tokens e lm_head numa precisão superior, se o método ou runtime o permitir — um padrão comum nas receitas do LLM Compressor.
  • Utilize amostras suficientes para estabilizar os intervalos das ativações. O exemplo de KV cache do vLLM define NUM_CALIB_SAMPLES = 512. Considere-o um exemplo documentado, não uma contagem universal. O número adequado de amostras depende do método, do modelo, do comprimento da sequência e da workload de produção.
  • Remova segredos e dados privados dos utilizadores antes de utilizar logs de produção.

Na avaliação, teste tanto a qualidade linguística como o comportamento do serving:

  • A perplexidade num corpus padrão deteta uma degradação geral da linguagem, mas o benchmark JarvisLabs é um lembrete útil de que a perplexidade e o débito podem evoluir de forma diferente.
  • As tarefas de domínio detetam falhas que a perplexidade oculta. Use o HumanEval para programação, o MMLU para conhecimento geral e o AIME ou o MATH-500 para raciocínio matemático quando esses domínios forem relevantes.
  • As verificações de formato são importantes para sistemas agentic. Teste a conformidade com o esquema JSON, o output em Markdown, o formato das chamadas a ferramentas e o comportamento de recusa, porque as avaliações de modelos quantizados podem não detetar falhas ao nível da aplicação, mesmo quando a precisão agregada no benchmark permanece estável.
  • Os testes de contexto longo detetam danos na quantização da cache KV. O needle-in-a-haystack é rudimentar, mas os resultados da quantização em contextos longos mostram por que razão estas verificações devem fazer parte do gate de deployment.
  • Os testes de carga devem reportar o débito, o TTFT, a latência entre tokens, a capacidade máxima do batch e o pico de memória. O vLLM expõe estas medições através de vllm bench serve.

Avalie rigorosamente os modelos com forte dependência de raciocínio. A quantização sub-4-bit ou W4A4 sem rotação pode prejudicar a precisão de raciocínio, mesmo quando a perplexidade de base parece estável — este é o principal alerta do estudo sobre modelos de raciocínio quantizados.


9. Fluxo de trabalho do repositório complementar

O repositório complementar, slavadubrov/model-compression-demo, destina-se a tornar o processo de decisão reproduzível. Usa uv e centra-se no planeamento, nas recipes, nos dry runs e nas configurações de benchmark baseadas nas mesmas fontes utilizadas aqui: vLLM, LLM Compressor, TensorRT-LLM e os artigos sobre os algoritmos.

O README público na revisão 8b45003849e830bed2ff341a9f027b017d932c1f foi verificado em 2026-08-16. O checkout complementar não está presente neste workspace, pelo que não pude executar aqui a respetiva CLI. Os comandos abaixo são ilustrativos até os executar a partir desse checkout fixo, e o plano de benchmark ainda precisa do hardware de serving pretendido.

Não copie o output da recipe FP8 dessa revisão fixa. O comando recipe --algorithm fp8-dynamic produz um modelo e um caminho de output internamente inconsistentes. O comando continua omitido aqui até o repositório complementar ser corrigido.

Clone-o e inspecione os algoritmos suportados:

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

Comece pelo planeamento e pelo dimensionamento:

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

Em seguida, gere uma recipe e faça uma pré-visualização da quantização antes de gastar tempo de 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

Para o planeamento do serving e dos benchmarks:

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

Por fim, compare os modelos base e comprimido com limiares explícitos:

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

Execute o trabalho pela ordem indicada: planeie o alvo, estime a memória, faça um dry run da recipe, faça o benchmark do serving e, em seguida, compare a qualidade com os limiares. Esta sequência reflete a separação feita neste artigo entre dimensionamento de memória, benchmarking do runtime e avaliação da qualidade.


10. Os modelos de diffusion precisam de um percurso separado

Os pipelines de diffusion e diffusion-transformer têm um comportamento de ativação diferente do dos LLMs autoregressivos. O SVDQuant trata a quantização de diffusion como um problema separado de outliers nas ativações.

Os LLMs autoregressivos geram um token de cada vez. Os modelos de diffusion executam passos repetidos de denoising, e as distribuições das ativações mudam ao longo do processo. Uma passagem de quantização padrão de 4 bits para LLMs pode reduzir a memória do modelo de diffusion, mas introduzir artefactos visuais graves. Métodos específicos para diffusion, como SVDQuant / Nunchaku e NVIDIA ModelOpt diffusion quantization, lidam com esse padrão de ativações diferente.

Use os pontos seguintes como heurísticas conservadoras, não como predefinições universais. O pipeline, o componente, o modelo e o runtime precisam de testes separados:

  1. Mantenha o VAE em 16 bits na primeira comparação. Esta heurística conservadora reduz uma fonte de artefactos de imagem. Teste precisões inferiores apenas quando o método e o pipeline-alvo as validarem.
  2. Comece pelo DiT ou backbone U-Net, porque este componente costuma concentrar a maior parte dos parâmetros. Esta é uma heurística, por isso confirme a memória, a latência e a qualidade da imagem para o pipeline-alvo. Os métodos de quantização para diffusion seguem a mesma abordagem ao nível dos componentes.
  3. Trate os text encoders separadamente. Quantizar T5-XXL ou CLIP pode afetar o alinhamento com o prompt ou a renderização de texto num determinado pipeline. Avalie-os de forma independente, em vez de assumir o comportamento genérico de um transformer.
  4. Use métodos conscientes de diffusion, como SVDQuant, quando os outliers nas ativações forem o principal problema.
  5. Avalie com imagens, não com métricas de texto. Verifique a adesão ao prompt, a renderização de texto, os tons de pele, o equilíbrio de cores, os detalhes finos, a latência e a VRAM.

Se o conjunto de avaliação contiver apenas prompts simples ou comuns, não detetará falhas em casos-limite. Inclua casos difíceis: texto pequeno, mãos, objetos repetidos, layouts estruturados e prompts com restrições negativas, porque as falhas da quantização de diffusion surgem visualmente, e não na perplexidade do modelo de linguagem.


11. Predefinições para produção

Para servir LLMs em contexto empresarial, comece por uma baseline BF16 no motor de serving exato que pretende utilizar. Se o objetivo for o throughput e o hardware o suportar, teste FP8 W8A8. Se o modelo não couber, teste AWQ ou GPTQ W4A16 com kernels da classe Marlin. Se o problema for o contexto longo ou a concorrência, teste a quantização FP8 da KV-cache. Se o problema forem prefixos repetidos, ative também o caching de prefixos. Coloque a versão comprimida em produção apenas quando tanto a qualidade como os benchmarks de serving forem aprovados.

Para inferência local e edge, comece por um ficheiro GGUF com Q4_K_M ou Q5_K_M. Passe para um GGUF Q8_0 quando a memória o permitir e a qualidade for mais importante do que o footprint. Descer abaixo de 4 bits deve ser o último recurso, não uma predefinição.

Para fine-tuning, use NF4 com QLoRA para treinar adapters de forma económica. Avalie o adapter na aplicação antes de fazer o merge. Depois do merge, exporte para o artefacto de serving de que realmente precisa: um ficheiro GGUF compatível com llama.cpp, um checkpoint AWQ/GPTQ/compressed-tensors, um checkpoint de serving FP8 ou BF16.

Para diffusion, comece por essas heurísticas conservadoras e teste visualmente cada combinação de pipeline/modelo/runtime. A perplexidade do texto não indica se um pipeline de imagens deixou de funcionar, por isso use evidências específicas de diffusion, como SVDQuant, e avaliação visual.


Referências

  • Benchmarks do vLLM da JarvisLabs: JarvisLabs, vLLM Quantization Complete Guide and Benchmarks, 2026. JarvisLabs.
  • Guia de quantização do Optimum da Hugging Face: Hugging Face, Quantization conceptual guide. Documentação.
  • Documentação de quantização do vLLM: projeto vLLM, Quantization. Documentação.
  • Documentação da cache KV quantizada do vLLM: projeto vLLM, Quantized KV Cache. Documentação.
  • Documentação de benchmarks do vLLM: projeto vLLM, vllm bench serve. Documentação.
  • Documentação do LLM Compressor: projeto vLLM, LLM Compressor. Documentação.
  • GPTQModel: ModelCloud, GPTQModel. GitHub.
  • Quantização do TensorRT-LLM: NVIDIA, TensorRT-LLM Quantization. Documentação.
  • NVIDIA NVFP4: NVIDIA, Introducing NVFP4 for Efficient and Accurate Low-Precision Inference. Blogue.
  • QuantizedCache da Hugging Face: Hugging Face, Cache strategies: Quantized cache. Documentação.
  • NVIDIA Model Optimizer: NVIDIA, Model Optimizer. GitHub.
  • Quantização com torchao: PyTorch, torchao quantization overview. Documentação.
  • Quantização com bitsandbytes: Hugging Face, bitsandbytes. Documentação.
  • HQQ: Dropbox, Half-Quadratic Quantization. GitHub.
  • PEFT: Hugging Face, Parameter-Efficient Fine-Tuning. Documentação.
  • Ollama: runtime local de modelos da Ollama. Site Web.
  • LM Studio: runtime local de IA do LM Studio. Site Web.
  • Estado do AutoGPTQ: repositório do AutoGPTQ, arquivado em abril de 2025. GitHub.
  • Estado do AutoAWQ: repositório do AutoAWQ, arquivado e descontinuado em maio de 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, abril de 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.
  • Avaliação de LLM Serving: Kurtic et al., “Give Me BF16 or Give Me Death”? Accuracy-Performance Trade-Offs in LLM Quantization, ACL 2025. arXiv:2411.02355.
  • Avaliação de quantização para contextos longos: Mekala et al., Does quantization affect models’ performance on long-context tasks?, arXiv:2505.20276. arXiv:2505.20276.
  • Avaliação de raciocínio: 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 e llama.cpp: ggml-org, GGUF file format e llama.cpp. GGUF, llama.cpp.
  • Documentação do GGUF no Hugging Face: Hugging Face, GGUF. Docs.
  • Repositório de referência: slavadubrov/model-compression-demo.