Otimização de Cache KV: Eficiência de Memória para LLMs em Produção
Atualizado em 11 de dezembro de 2025
Atualização de Dezembro de 2025: Inferência tradicional desperdiçando 60-80% da memória de cache KV através de fragmentação. PagedAttention do vLLM reduzindo desperdício para menos de 4%, permitindo 2-4x de throughput. Modelo de 70B com contexto de 8K requerendo ~20GB de cache por requisição, ~640GB para batch de 32. Cache KV agora frequentemente excede os pesos do modelo no consumo de memória. Técnicas de otimização permitindo contextos mais longos e batches maiores no hardware existente.
Sistemas de inferência de LLM desperdiçam 60-80% da memória de cache KV alocada através de fragmentação e sobre-alocação.¹ Esse desperdício se traduz diretamente em throughput reduzido, custos mais altos e limites artificiais nos comprimentos de contexto. PagedAttention, introduzido pelo vLLM, reduziu o desperdício de cache KV para menos de 4%, permitindo melhorias de throughput de 2-4x que transformaram a economia de inferência em produção.² Compreender técnicas de otimização de cache KV ajuda organizações a maximizar a utilização de GPU e atender mais usuários com a infraestrutura existente.
O gerenciamento de cache KV se tornou o gargalo crítico para implantações de LLM em produção. O consumo de memória cresce linearmente com o comprimento da sequência e tamanho do batch, esgotando rapidamente até GPUs de alta memória como H100 e H200. Dominar técnicas de otimização de cache permite contextos mais longos, batches maiores e inferência mais econômica em escala.
Por que o cache KV é importante
Modelos Transformer calculam atenção sobre todos os tokens anteriores ao gerar cada novo token. Sem cache, gerar 1.000 tokens requer recalcular a atenção do zero 1.000 vezes—aumentando quadraticamente o custo com o comprimento da sequência.
Solução de cache KV: Armazenar tensores de chave e valor de tokens anteriores, reutilizando-os para cálculos de atenção subsequentes. Cada novo token calcula atenção contra valores em cache ao invés de regenerá-los.
Impacto na memória: Um modelo de 70B parâmetros gerando 8.192 tokens com batch size 32 requer aproximadamente 40-50GB de memória de cache KV sozinho—frequentemente excedendo os próprios pesos do modelo.³
O problema de escala: A memória de cache KV cresce como:
Memória = batch_size × seq_length × num_layers × 2 × hidden_dim × precision_bytes
Para Llama 3.1-70B com FP16: - Cache por token: ~2.5MB - Contexto de 8K: ~20GB por requisição - Batch de 32: ~640GB de cache KV total
PagedAttention: a otimização fundamental
O PagedAttention do vLLM revolucionou o gerenciamento de cache KV tratando a memória da GPU como memória virtual de sistema operacional:⁴
Como funciona
Alocação tradicional: Reservar blocos de memória contíguos para o comprimento máximo possível de sequência. Um contexto máximo de 4K aloca 4K de cache mesmo para requisições de 100 tokens, desperdiçando 97,5% da memória reservada.
Alocação paginada: Dividir o cache KV em blocos de tamanho fixo (páginas). Alocar páginas sob demanda conforme as sequências crescem. Liberar páginas quando as sequências completam.
Mapeamento de tabela de blocos: Como tabelas de páginas do SO, PagedAttention mantém mapeamentos entre posições lógicas de sequência e localizações físicas de memória. Sequências veem memória contínua enquanto o armazenamento físico permanece não contíguo.
Impacto no desempenho
- Desperdício de memória: 60-80% → menos de 4%
- Throughput: melhoria de 2-4x versus alocação tradicional
- Fragmentação de memória: Virtualmente eliminada⁵
Implementação no vLLM
from vllm import LLM, SamplingParams
# PagedAttention habilitado por padrão
llm = LLM(
model="meta-llama/Llama-3.1-70B-Instruct",
tensor_parallel_size=4,
gpu_memory_utilization=0.90, # Usar 90% da memória da GPU
max_model_len=32768,
)
O vLLM gerencia automaticamente alocação de páginas, desalocação e compartilhamento de memória sem configuração explícita.
Cache de prefixo e compartilhamento de memória
PagedAttention permite compartilhamento eficiente de memória entre requisições com prefixos comuns:
Prompts de sistema compartilhados: Quando múltiplas requisições usam prompts de sistema idênticos, páginas físicas armazenando esses tokens são compartilhadas ao invés de duplicadas.
Cache automático de prefixo: O Automatic Prefix Caching (APC) do vLLM detecta prefixos comuns entre requisições e compartilha blocos de cache KV automaticamente:
llm = LLM(
model="meta-llama/Llama-3.1-8B-Instruct",
enable_prefix_caching=True,
)
Impacto em produção: Aplicações com prompts de sistema consistentes ou contexto repetido (RAG com documentos comuns, exemplos few-shot) veem economia dramática de memória e redução de latência. Taxas de acerto de cache de 87%+ são alcançáveis com prompts bem estruturados.⁶
Quantização de cache KV
Comprimir valores de cache KV reduz requisitos de memória ao custo de degradação menor de precisão:
Cache KV FP8
GPUs Hopper e Blackwell suportam cache KV FP8 nativo:
# Cache KV FP8 no vLLM
llm = LLM(
model="meta-llama/Llama-3.1-70B-Instruct",
kv_cache_dtype="fp8",
)
FP8 reduz pela metade a memória de cache KV versus FP16 com impacto mínimo na qualidade para a maioria das aplicações. A otimização se torna essencial para inferência de contexto longo onde o cache domina o consumo de memória.
Cache KV INT4
Suporte experimental a cache KV de 4 bits reduz ainda mais a memória:⁷ - Redução de memória: 4x versus FP16 - Impacto na qualidade: Dependente da tarefa, requer avaliação - Melhor para: Aplicações de contexto longo com restrição de memória
Seleção de quantização
| Precisão | Economia de Memória | Impacto na Qualidade | Caso de Uso |
|---|---|---|---|
| FP16 | Base | Nenhum | Padrão, crítico para qualidade |
| FP8 | 50% | Mínimo | Inferência em produção |
| INT8 | 50% | Baixo | Implantações sensíveis a custo |
| INT4 | 75% | Moderado | Restrições extremas de memória |
Estratégias de evicção de cache
Quando a pressão de memória excede a capacidade disponível, políticas de evicção de cache determinam quais tokens descartar:
Atenção de janela deslizante
Manter apenas tokens recentes no cache, descartando contexto mais antigo:
# Janela deslizante conceitual
def sliding_window_cache(kv_cache, window_size):
if len(kv_cache) > window_size:
kv_cache = kv_cache[-window_size:]
return kv_cache
Simples mas eficaz para aplicações onde contexto recente importa mais. Janela deslizante arquitetural (como Mistral) implementa isso nativamente.
Evicção baseada em atenção
Remover tokens com menores scores de atenção, mantendo contexto importante:
PagedEviction (2025): Algoritmo de evicção em nível de bloco adaptado para PagedAttention que identifica e remove blocos de baixa importância sem modificar kernels CUDA.⁸
Cache guiado por entropia: Alocar orçamento de cache baseado na entropia de atenção da camada—camadas com padrões de atenção mais amplos recebem mais cache, camadas focadas recebem menos.⁹
Streaming LLM
Para geração de comprimento infinito, Streaming LLM mantém: - Tokens iniciais "attention sink" (primeiros 4-8 tokens) - Tokens recentes dentro da janela deslizante - Descarta contexto do meio
A abordagem permite geração teoricamente ilimitada com memória fixa, embora a qualidade degrade para tarefas que requerem dependências de longo alcance.
Offloading de cache KV
Quando a memória da GPU se mostra insuficiente, transferir cache para camadas de armazenamento mais lentas:
Offloading para CPU
Mover caches de sequências inativas para RAM do sistema:
# Integração LMCache para offloading
from lmcache import LMCacheEngine
cache_engine = LMCacheEngine(
backend="cpu",
max_gpu_cache_size="20GB",
cpu_cache_size="100GB",
)
Impacto na latência: Transferência CPU-GPU adiciona 10-50ms por recuperação de cache. Adequado para cargas de trabalho em batch ou quando limites de memória da GPU impedem o serviço completamente.
Desempenho: LMCache com vLLM alcança redução de latência de 3-10x versus recomputação ao fazer cache na memória da CPU ao invés de regenerar.¹⁰
Offloading para disco
Para casos extremos, cache em armazenamento NVMe: - Latência: 100-500ms por recuperação - Caso de uso: Contextos muito longos que seriam impossíveis de outra forma - Não adequado para aplicações interativas
Cache em camadas
Sistemas de produção frequentemente implementam cache multi-camada:
- GPU HBM: Sequências quentes gerando ativamente
- CPU RAM: Sequências mornas recentemente ativas
- NVMe SSD: Sequências frias para potencial reutilização
Políticas inteligentes de promoção e rebaixamento movem cache entre camadas baseado em padrões de acesso.
Roteamento consciente de cache KV
Inferência distribuída se beneficia de rotear requisições para pods que mantêm cache relevante:
Framework llm-d
Framework nativo de Kubernetes com roteamento consciente de cache KV:¹¹
# Configuração de roteamento de cache llm-d
routing:
strategy: kv_cache_aware
cache_hit_weight: 0.8
load_balance_weight: 0.2
Resultados de desempenho: - Taxa de acerto de cache de 87% com cargas de trabalho pesadas em prefixo - Time-to-first-token 88% mais rápido para acertos de cache quente - Redução significativa em computação redundante através do cluster
Padrões de implementação
Sessões sticky: Rotear requisições da mesma conversa para o mesmo pod.
Hash de prefixo: Aplicar hash em prompts de sistema para determinar roteamento de pod, garantindo acertos de cache de prefixo.
Roteamento consciente de carga: Balancear localidade de cache contra utilização de pod para prevenir pontos quentes.
Guia de dimensionamento para produção
Estimativa de memória
Calcular requisitos de cache KV antes da implantação:
def estimate_kv_cache_memory(
num_layers: int,
hidden_dim: int,
num_kv_heads: int,
head_dim: int,
max_seq_len: int,
max_batch_size: int,
precision_bytes: int = 2, # FP16
) -> float:
"""Estimar memória de cache KV em GB"""
per_token = num_layers * 2 * num_kv_heads * head_dim * precision_bytes
total = per_token * max_seq_len * max_batch_size
return total / (1024 ** 3)
# Exemplo Llama 3.1-70B
memory_gb = estimate_kv_cache_memory(
num_layers=80,
hidden_dim=8192,
num_kv_heads=8, # GQA
head_dim=128,
max_seq_len=8192,
max_batch_size=32,
)
print(f"Memória de cache KV: {memory_gb:.1f} GB")
Planejamento de capacidade
Regra geral: Reservar 40-60% da memória da GPU para cache KV, o restante para pesos do modelo e ativações.
Exemplo H100 80GB: - Pesos do modelo (70B FP16): ~140GB → 2x GPU com paralelismo de tensor - Disponível por GPU para cache: ~30-35GB após pesos e overhead - Máximo de sequências concorrentes: Depende do comprimento médio de contexto
Prioridade de otimização
- Habilitar PagedAttention: Padrão no vLLM, grande ganho de eficiência
- Habilitar cache de prefixo: Se cargas de trabalho têm prefixos comuns
- Implementar cache KV FP8: Ao usar GPUs Hopper/Blackwell
- Adicionar roteamento consciente de cache: Em escala de cluster com inferência distribuída
- Considerar offloading: Apenas quando memória da GPU se mostrar insuficiente
Monitoramento e observabilidade
Rastrear métricas de cache KV em produção:
Métricas-chave: - Utilização de cache: Porcentagem do cache alocado em uso - Taxa de acerto de cache: Eficácia do cache de prefixo - Taxa de evicção: Frequência de overflow de cache - Fragmentação de memória: Espaço desperdiçado dentro de blocos alocados
Endpoint de métricas do vLLM:
# Métricas Prometheus disponíveis em /metrics
# kv_cache_usage_percent
# kv_cache_total_blocks
# kv_cache_used_blocks
# prefix_cache_hit_rate
Limiares de alerta: - Utilização de cache > 90%: Escalar capacidade ou reduzir batch size - Taxa de acerto < 50%: Revisar configuração de cache de prefixo - Taxa de evicção alta: Aumentar alocação de memória ou otimizar prompts
Organizações implantando inferência de LLM em produção podem aproveitar a expertise em infraestrutura da Introl para planejamento de capacidade de GPU e otimização em implantações globais.
O imperativo da eficiência de memória
A otimização de cache KV representa uma das melhorias de maior impacto para implantações de LLM em produção. PagedAttention sozinho entrega melhorias de throughput de 2-4x—equivalente a dobrar ou quadruplicar o investimento em GPU sem custo adicional de hardware.
O panorama de otimização continua evoluindo. O FastGen da Microsoft demonstrou redução de memória de 50% através de compressão adaptativa. Cache guiado por entropia aloca orçamento inteligentemente entre camadas. Roteamento consciente de cache permite ganhos de eficiência em escala de cluster anteriormente impossíveis.
Para organizações executando inferência em escala, a otimização de cache KV deve figurar entre as primeiras otimizações avaliadas. As técnicas requerem míni
[Conteúdo truncado para tradução]