./insights

Insights / Guia

Guia

GPU para inferência de LLM: memória, throughput e custo

Dimensionamento de GPU para inferência de LLM: pesos, KV cache, batching, latência, concorrência, gatilhos de escala, custo por milhão de tokens e exemplo prático.

Engenharia Vonahost11 min de leitura

A maioria dos erros de dimensionamento de GPU para inferência de grandes modelos de linguagem acontece antes de qualquer hardware ser encomendado. Uma equipe escolhe um modelo, encontra uma GPU com memória suficiente para carregá-lo e conclui que o trabalho está feito.

Carregar o modelo é apenas a primeira restrição. A capacidade de inferência é definida por três fatores em conjunto: memória para os pesos, memória para o cache de atenção de cada requisição ativa e a taxa com que a GPU consegue gerar tokens dentro da meta de latência que você prometeu.

WEIGHTSKVRUNTIME
Fig. 1Um orçamento de memória de GPU: pesos, cache e overhead.

Comece pela carga de trabalho, não pela GPU

Antes de comparar aceleradores, anote o que o serviço precisa fazer.

  • Modelo e precisão. Número de parâmetros, arquitetura (camadas, attention heads, key/value heads, dimensão dos heads) e a precisão com que você está disposto a servir.
  • Tamanhos de contexto. O número típico e o percentil 95 de tokens de entrada por requisição, além do tamanho típico e máximo da saída.
  • Perfil do tráfego. Requisições por segundo na hora mais movimentada, não a média diária, e quão abruptos são os picos.
  • Metas de latência. Tempo até o primeiro token (quanto tempo até o usuário ver algo) e tempo por token de saída (com que velocidade o texto flui depois disso).
  • Isolamento e localização. Se prompts e saídas podem deixar um determinado ambiente ou país, o que pode descartar capacidade compartilhada independentemente do preço.

Chat interativo, busca com geração aumentada por recuperação, sumarização de documentos e pontuação em lote offline podem rodar o mesmo modelo com demandas de hardware completamente diferentes. Uma tarefa de sumarização com 8.000 tokens de entrada e uma resposta de 200 tokens exige partes do sistema diferentes das de um assistente de chat com 1.000 tokens de entrada e 600 tokens de saída.

Memória, parte um: os pesos do modelo

Multiplique o número de parâmetros pelos bytes por parâmetro da precisão em que você vai servir o modelo. As regras práticas comuns são 2 bytes por parâmetro em FP16 ou BF16, 1 byte em INT8 ou FP8 e cerca de 0,5 byte em formatos de 4 bits, mais uma pequena quantidade para as escalas de quantização.

  • 8B parâmetros. Cerca de 16 GB em FP16, 8 GB em INT8 e 4 a 5 GB em INT4.
  • 70B parâmetros. Cerca de 140 GB em FP16, 70 GB em INT8 e 35 a 40 GB em INT4.
  • Modelos da classe de 400B parâmetros. Cerca de 800 GB em FP16, 400 GB em INT8 e 200 a 230 GB em INT4, o que exige um nó com várias GPUs mesmo com quantização.

O contexto CUDA, os buffers de ativação, os buffers de comunicação para paralelismo de tensores e a fragmentação normalmente ocupam vários gigabytes por GPU. Engines de serving como o vLLM permitem definir a fração da memória da GPU que podem reservar; um valor de planejamento de 85 a 90 por cento da memória física como utilizável é um ponto de partida razoável.

Pesos de 8 bits são amplamente usados em produção, com pequena perda mensurável na maioria das tarefas. Pesos de 4 bits reduzem a memória pela metade outra vez, mas podem degradar de forma mais perceptível o raciocínio, o código e a saída multilíngue, então avalie com os seus próprios prompts antes de planejar a capacidade com base neles.

Memória, parte dois: o KV cache define a concorrência

Durante a geração, cada requisição mantém as chaves e os valores de atenção de cada token que já viu. Esse KV cache cresce com o tamanho do contexto e com o número de requisições simultâneas, e em um servidor movimentado muitas vezes ocupa mais memória do que os pesos.

O tamanho por token é: 2 (uma key e um value) vezes o número de camadas, vezes o número de cabeças de key/value, vezes a dimensão das cabeças, vezes os bytes por elemento. Para um modelo típico da classe de 70B com grouped-query attention (80 camadas, 8 cabeças de key/value, dimensão de cabeça 128) em FP16, isso dá 2 x 80 x 8 x 128 x 2 bytes, cerca de 320 KB por token.

A 320 KB por token, uma requisição com 4.000 tokens de contexto usa cerca de 1,3 GB. Cinquenta requisições desse tipo precisam de cerca de 65 GB, quase o tamanho dos próprios pesos em INT8.

  • Alocação paginada. Engines que alocam o cache em blocos pequenos (paged attention) reservam memória apenas para os tokens que existem, de modo que você pode planejar com base no contexto médio, não no contexto máximo, com uma margem para requisições longas.
  • Quantização do cache. Armazenar o KV cache em FP8 reduz seu tamanho aproximadamente pela metade e dobra o número de sequências que cabem, geralmente com um custo modesto de qualidade que deve ser testado.
  • Prefix caching. Quando muitas requisições compartilham um prompt de sistema ou um documento longo, reutilizar suas chaves e valores em cache economiza memória e computação de prefill.
  • Limites de contexto. Limitar o contexto máximo por requisição costuma ser a alavanca de capacidade mais barata disponível, porque um punhado de requisições muito longas pode deixar todas as outras sem recursos.
QUEUEBATCH
Fig. 2Requisições agrupadas em lotes antes do servidor GPU.

Throughput, latência e batching

A inferência tem duas fases, com gargalos diferentes. O prefill processa o prompt inteiro de uma vez e é limitado pela capacidade de computação; uma aproximação útil é de 2 operações de ponto flutuante por parâmetro por token, de modo que um modelo de 70B precisa de cerca de 140 GFLOP para cada token de entrada. Em seguida, o decode produz um token por vez para cada requisição e é limitado pela largura de banda de memória, porque cada passo lê os pesos e o KV cache da requisição na memória da GPU.

Isso dá um teto simples para a velocidade de um único fluxo: a largura de banda de memória dividida pelos bytes lidos por token. Um modelo com 70 GB de pesos INT8 distribuídos em duas GPUs com cerca de 2 TB/s cada consegue ler os pesos completos no máximo cerca de 57 vezes por segundo, então uma requisição não consegue gerar mais do que aproximadamente 57 tokens por segundo nessa configuração, e na prática será menos.

O batching é o que torna a inferência economicamente viável. O continuous batching, hoje padrão em engines como o vLLM e em stacks baseadas no Triton, admite novas requisições no lote em execução a cada passo, em vez de esperar que um lote termine. O throughput agregado cresce fortemente com o tamanho do lote até que o KV cache se esgote ou a computação se torne o limite.

O custo do batching é a latência. O planejamento de capacidade é, portanto, uma troca: escolha o maior batch que ainda cumpra as metas de tempo até o primeiro token e de tempo por token de saída no percentil 95, e dimensione o parque a partir do throughput medido nesse ponto, e não do pico de throughput de um gráfico de benchmark.

Como estimar a concorrência a partir do tráfego

A concorrência, o número de requisições em andamento ao mesmo tempo, é o que consome o KV cache e os slots de lote. Você pode estimá-la com a lei de Little: a concorrência média é igual à taxa de chegada multiplicada pelo tempo médio que cada requisição passa no sistema.

Se o pico de tráfego é de 5 requisições por segundo e cada requisição leva 14 segundos da chegada até o último token (cerca de 1 segundo de fila e prefill, mais 400 tokens de saída a 30 tokens por segundo), o sistema mantém cerca de 70 requisições simultâneas. Multiplique isso pela média de tokens mantidos por requisição e pelo tamanho do KV por token, e você terá a memória de cache que o pico exige.

  • Use o pico, não a média. O tráfego interativo costuma ficar em duas a quatro vezes a sua média diária durante a hora mais movimentada.
  • Observe o tamanho da saída. A concorrência cresce com o tempo que as requisições permanecem abertas, e os tokens de saída são a parte lenta, então dobrar o tamanho médio da saída praticamente dobra a concorrência.
  • Considere retentativas e agentes. Agentes que chamam ferramentas e retentativas automáticas podem disparar várias chamadas ao modelo por ação do usuário, multiplicando a taxa efetiva de chegada.

Um exemplo prático

Considere um assistente interno construído sobre um modelo da classe de 70B com grouped-query attention, servido com pesos em INT8 e KV cache em FP16. A carga de pico é de 5 requisições por segundo. As requisições têm em média 2.000 tokens de entrada e 400 tokens de saída. As metas são menos de 1,5 segundo até o primeiro token e pelo menos 25 tokens por segundo de streaming no percentil 95. O hardware candidato são GPUs de 80 GB com cerca de 2 TB/s de banda de memória cada.

  • Pesos. 70B parâmetros a 1 byte cada dão cerca de 70 GB. Uma GPU de 80 GB não comporta isso mais um cache útil, então a unidade mínima é de duas GPUs com tensor parallelism: 160 GB físicos, cerca de 144 GB utilizáveis a 90 por cento.
  • Orçamento de cache. 144 GB menos 70 GB de pesos deixam cerca de 74 GB para o KV cache.
  • Demanda de cache. Pela lei de Little, cerca de 70 requisições simultâneas. Cada uma mantém cerca de 2.400 tokens ao final, aproximadamente 0,8 GB a 320 KB por token, de modo que a demanda de pico fica em torno de 55 GB. Cabe, com cerca de 25 por cento de folga.
  • Velocidade de decode. Cada passo lê cerca de 35 GB de pesos por GPU, mais a parcela do cache daquela GPU, cerca de 27 GB no pico. A 2 TB/s, isso dá aproximadamente 31 ms por passo antes do overhead, ou cerca de 30 tokens por segundo por stream e cerca de 2.000 tokens de saída por segundo no agregado. É exatamente o volume de 2.000 tokens por segundo que o pico exige, sem nenhuma margem.
  • Carga de prefill. 5 requisições x 2.000 tokens são 10.000 tokens de entrada por segundo, cerca de 1,4 PFLOP/s de trabalho. Isso disputa as mesmas GPUs com o decode e vai derrubar o streaming abaixo da meta durante os picos.

A conclusão é que uma réplica com duas GPUs comporta o modelo e o cache, mas não tem folga de throughput no pico nem redundância. Duas réplicas, quatro GPUs no total atrás de um load balancer, reduzem aproximadamente pela metade a carga por réplica, mantêm a latência dentro da meta durante os picos e permitem que uma réplica seja drenada para manutenção nos horários de menor movimento.

LBR1R2
Fig. 3Réplicas atrás de um balanceador de carga, com espaço para escalar horizontalmente.

Utilização, escalonamento horizontal e custo por milhão de tokens

Os percentuais de utilização de GPU reportados pelas ferramentas de monitoramento podem enganar, porque uma GPU ocupada lendo memória para um lote de uma única requisição parece totalmente utilizada enquanto faz pouco trabalho útil. Em vez disso, acompanhe as métricas que correspondem à capacidade: tokens gerados por segundo, ocupação do KV cache, requisições aguardando na fila e percentis de latência para o tempo até o primeiro token e o tempo por token de saída.

  • Escale horizontalmente quando surgirem filas. Enfileiramento sustentado no pico, ou ocupação do KV cache acima de cerca de 90 por cento com requisições sendo preemptadas, significa que a réplica está cheia.
  • Escale horizontalmente quando a latência se desviar. Se o percentil 95 do tempo por token de saída estiver se aproximando da meta enquanto o throughput permanece estável, o lote está grande demais para a réplica.
  • Escale verticalmente quando o modelo não couber. Mais memória por GPU ou mais GPUs por réplica ajudam quando os pesos e o cache mínimo não cabem, ou quando contextos longos predominam.
  • Mantenha N+1. Um serviço importante deve sobreviver à perda de uma réplica no pico, o que costuma determinar o número de réplicas mais do que o throughput bruto.

O custo por milhão de tokens decorre diretamente desses números: divida o custo por hora da frota pelos milhões de tokens que ela produz por hora. Usando um valor puramente hipotético de US$ 2,50 por GPU-hora, o exemplo com quatro GPUs custa US$ 10 por hora. Com a saída plena de pico de 2.000 tokens por segundo, ele produz 7,2 milhões de tokens de saída por hora, cerca de US$ 1,40 por milhão. Se a carga média ao longo do dia for de 30 por cento do pico, a mesma frota produz cerca de 2,2 milhões de tokens por hora e o custo efetivo sobe para cerca de US$ 4,60 por milhão.

A utilização pesa mais no custo unitário do que o valor por hora. Cargas de trabalho que podem ser adiadas, como sumarização em lote, reprocessamento de embeddings ou rodadas de avaliação, podem ocupar as horas ociosas da capacidade interativa e reduzir o custo combinado.

Checklist de planejamento de capacidade

  • Registre parâmetros, camadas, cabeças key/value e dimensão das cabeças.
  • Defina a precisão dos pesos e do KV cache. Teste a qualidade com seus próprios prompts.
  • Calcule a memória dos pesos e o mínimo de GPUs por réplica. Reserve 10 a 15 por cento para overhead.
  • Calcule bytes de KV cache por token e o orçamento após os pesos.
  • Meça ou estime o pico de RPS e a média de tokens de entrada e saída.
  • Use a lei de Little para estimar a concorrência de pico e o cache necessário.
  • Defina metas p95 para o tempo até o primeiro token e o tempo por token de saída.
  • Faça benchmark do engine na concorrência-alvo. Registre os tokens/s sustentados por réplica.
  • Dimensione réplicas pelo throughput de pico com folga, mais uma para N+1.
  • Limite contexto e saída por requisição. Use prefix caching em prompts repetidos.
  • Escale com base na profundidade da fila, no uso do cache e na latência, não só na GPU.
  • Calcule o custo por milhão de tokens no pico e na carga média. Lotes nas horas ociosas.
  • Confirme onde prompts, saídas e pesos podem residir e só então escolha a localização.

Como a Vonahost pode ajudar

A Vonahost cota a capacidade de GPU por projeto, com modelo de GPU, quantidade e prazo de entrega confirmados por escrito, e oferece suporte a implantações privadas em que os dados e os modelos permanecem no ambiente do cliente. As implantações usam ferramentas padrão como PyTorch, vLLM, Triton e Kubernetes, de modo que o método de dimensionamento acima se aplica diretamente a um benchmark no hardware proposto.

Toda proposta da Vonahost especifica a configuração, a localização, as responsabilidades e o preço mensal em dólares americanos, e os clientes escolhem o país onde cada servidor roda.

./insights

Continue lendo.

Próximo passo

Converse sobre isso com um engenheiro.

Descreva a carga de trabalho e as restrições. Retornamos uma recomendação, uma localização e um preço mensal em dólares americanos.