Inteligência artificial, sem ruído.
Tutoriais6 min

O roteiro completo para dominar a otimização de inferência em LLMs

Guia prático das 7 técnicas que aceleram LLMs em produção — do cache KV à decodificação especulativa — para servir mais requisições com menor custo.

O roteiro completo para dominar a otimização de inferência em LLMs

Fazer um modelo de linguagem grande gerar a resposta correta já é, para a maioria dos times, um problema resolvido. O que ainda derruba sistemas em produção é conseguir que ele responda rápido o suficiente, barato o suficiente e de forma confiável. Basta a fila de requisições crescer para o modelo estourar as metas de latência — e os custos escalarem muito além do previsto quando o tamanho do lote e o comprimento do contexto aumentam.

É exatamente essa lacuna que a otimização de inferência fecha: o mesmo modelo passa a atender mais requisições, mais rápido e com menor custo, sem tocar no treinamento. As técnicas vão desde ajustes de escalonamento (que não exigem nenhuma mudança no modelo) até variantes de atenção embutidas na própria arquitetura.

Por que isso importa agora

Com a explosão de aplicações de IA em produção — de chatbots a pipelines de RAG e agentes — o custo de servir um LLM virou a linha que separa projetos viáveis de prejuízo. Entender onde está o gargalo (computação ou memória) é o primeiro passo para cortar custos de infraestrutura sem sacrificar qualidade.

Passo 1: as duas fases da inferência

Toda passagem por um LLM decoder-only tem duas fases com características de desempenho opostas.

  • Prefill (pré-preenchimento): o modelo processa todos os tokens de entrada de uma vez para calcular os estados intermediários (tensores de chave e valor). Como a entrada inteira é conhecida de antemão, essa computação é altamente paralelizável e satura a GPU. O prefill é limitado por computação e define o tempo até o primeiro token (TTFT).
  • Decode (decodificação): os tokens de saída são gerados um a um, de forma autorregressiva. Como cada token depende de todos os anteriores, não dá para paralelizar dentro de uma mesma sequência. O gargalo muda: a GPU passa a maior parte do tempo esperando dados virem da memória. O decode é limitado por largura de banda de memória e define os tokens por segundo (TPS).

Entender essa distinção explica por que benchmarks simples enganam: otimizar TTFT não melhora necessariamente o TPS, e a técnica certa depende da métrica que o seu caso de uso realmente valoriza.

Passo 2: cache KV e o problema de memória

A otimização mais fundamental do decode é o cache KV: em vez de recomputar os tensores de chave e valor de todos os tokens anteriores a cada passo, o modelo os guarda na memória da GPU e os reutiliza. É uma troca de memória por computação — vantajosa quando computação é cara e há memória disponível.

O problema: os requisitos de memória do cache KV escalam com tamanho do lote e comprimento da sequência ao mesmo tempo. Num modelo de 7B parâmetros em 16 bits, só o cache KV pode consumir vários gigabytes por requisição em sequências moderadas.

Duas técnicas resolvem isso. O PagedAttention (usado por padrão no vLLM) divide o cache em blocos de tamanho fixo alocados sob demanda, eliminando a fragmentação de pré-reservar a sequência máxima. O prefix caching reaproveita o cache de um prefixo comum (prompt de sistema, documento analisado) entre requisições que o compartilham — uma economia enorme em pipelines de RAG.

Passo 3: batching para aproveitar a GPU

Uma requisição por vez deixa a GPU ociosa. Como os pesos são carregados na memória a cada passada independentemente do lote, o custo amortizado por token cai conforme o lote cresce.

  • Static batching: espera formar um lote fixo. O problema é que o lote só avança quando a requisição mais longa termina — as mais curtas ficam ociosas.
  • Dynamic batching: agrupa requisições que chegam numa janela curta, com tamanho máximo e timeout.
  • Continuous (in-flight) batching: desacopla a conclusão de uma sequência das fronteiras do lote. Assim que uma sequência termina, ela sai e uma nova entra no lugar, mantendo a GPU cheia mesmo com tamanhos de saída muito variáveis. É o padrão em vLLM e TensorRT-LLM.

Passo 4: otimizando a atenção

A atenção domina a computação na maioria das passadas. A multi-query attention (MQA) faz todos os heads de query compartilharem um único conjunto de chaves e valores, reduzindo o tráfego de memória no decode (com pequena perda de precisão). A grouped-query attention (GQA) fica no meio do caminho entre MHA e MQA, preservando mais capacidade de modelagem. Já o FlashAttention não muda a arquitetura: reordena a computação e usa tiling para manter valores intermediários na SRAM (mais rápida) em vez da memória global — um substituto direto, sem retreinamento, e uma das otimizações mais fáceis de aplicar.

Passo 5: compressão de modelo

Se as técnicas anteriores melhoram como o modelo é servido, a compressão reduz o que precisa ser servido.

  • Quantização: reduz a precisão dos pesos. Um modelo de 7B cai de ~14 GB (FP16) para ~3,5 GB (INT4) — a diferença entre precisar de uma GPU de datacenter e de uma placa de consumo. GPTQ e AWQ tornaram a quantização de 4 bits prática com perda mínima.
  • Esparsidade: explora o fato de muitos pesos serem próximos de zero. GPUs Ampere+ aceleram esparsidade estruturada 2:4 em até 2x.
  • Destilação de conhecimento: treina um modelo “aluno” menor para reproduzir o comportamento de um “professor” maior — geralmente melhor que comprimir o original quando a latência é o fator crítico.

Passo 6: decodificação especulativa

O gargalo autorregressivo (cada token espera o anterior) é o mais difícil de quebrar. A decodificação especulativa contorna isso sem violar a matemática: um modelo “rascunho” pequeno gera vários tokens candidatos, e o modelo completo os verifica em paralelo. Onde há concordância, os tokens são aceitos; na primeira discordância, o resto é descartado. A garantia de corretude é exata — e o ganho vem de gerar múltiplos tokens por chamada ao modelo completo. É mais impactante em cenários de baixa latência e requisição única, como chat interativo.

Passo 7: escalando com paralelismo

Quando o modelo não cabe numa GPU só, o paralelismo distribui a carga. O tensor parallelism divide as camadas entre GPUs; o pipeline parallelism divide o modelo verticalmente (com “bolhas” de ociosidade reduzidas por microbatching). A disagregação prefill/decode — padrão arquitetural mais recente — roteia as duas fases para pools de hardware separados, cada um otimizado para o seu gargalo, impedindo que prefill longos bloqueiem a capacidade de decode.

Resumo: o mapa das técnicas

TécnicaO que resolve
Cache KV + PagedAttentionEconomia de memória no decode
Continuous batchingUtilização da GPU com saídas variáveis
GQA / FlashAttentionMenos tráfego de memória na atenção
Quantização / esparsidadeModelo menor, menor custo por token
Decodificação especulativaMenor latência em chat
Paralelismo / disagregaçãoModelos maiores, mais throughput

A combinação certa depende das suas metas de latência e throughput, do comprimento de contexto e do orçamento de hardware. Perfile a sua carga real e adicione as técnicas em ordem de impacto.



Descubra mais sobre noticiAI

Assine para receber nossas notícias mais recentes por e-mail.

R
Sobre o autorRedação Noticiai

Equipe editorial dedicada a explicar inteligência artificial com clareza, independência e contexto.