Pular para o conteúdo
Fantástico Mundo de Jon
RSS

Quanta VRAM um LLM realmente ocupa

A conta de cabeça — parâmetros vezes bits — erra por vários gigabytes, porque ignora o KV cache. Aqui está a conta completa, com a fórmula, os números e como conferir na sua GPU.

Com pressa? Peça o TL;DR ao Claude — ele lê a página e resume.

A pergunta que mais recebo sobre rodar modelo local é sempre a mesma: cabe na minha placa?

E quase todo mundo faz a mesma conta errada. Pega o número de parâmetros, multiplica pelos bits da quantização, divide por oito e conclui que um modelo de 32B em Q4 ocupa 20 GB — logo, cabe folgado numa placa de 24 GB.

Aí carrega o modelo e a GPU estoura com 8 mil tokens de contexto.

O problema não é a conta. É que ela responde só um terço da pergunta. A memória que um modelo ocupa tem três parcelas, e a segunda cresce com o tamanho da conversa.

Parcela 1: os pesos

Essa é a parte fácil, e é a única que a maioria calcula. Cada parâmetro ocupa um número de bits que depende da quantização:

Quantização bits/peso bytes/peso
FP16 (sem quantizar) 16,0 2,00
Q8_0 8,5 1,06
Q6_K 6,6 0,82
Q5_K_M 5,7 0,71
Q4_K_M 4,9 0,61
Valores médios efetivos dos K-quants do llama.cpp. Não são exatos: as K-quants usam precisões diferentes por camada, e o número real varia ~2% entre arquiteturas. Confira sempre o tamanho do arquivo .gguf.

Repare que Q4_K_M não dá 4 bits por peso, e sim ~4,9. As K-quants guardam as camadas sensíveis (atenção, embeddings) com mais precisão do que o nome sugere. Quem calcula com 4,0 subestima o modelo em quase 20%.

Multiplicando pelos tamanhos mais comuns:

Modelo FP16 Q8_0 Q6_K Q4_K_M
8B 16,1 8,5 6,6 4,9
12B 24,4 13,0 10,1 7,5
32B 65,6 34,9 27,1 20,1
70B 141,2 75,0 58,2 43,2
Peso dos parâmetros em GB decimais (10⁹ bytes), a partir da contagem real de parâmetros de cada família. É só a primeira parcela — falta o KV cache.

É daqui que sai o número que todo mundo repete: 32B em Q4 = 20 GB. Está certo. E está incompleto.

Parcela 2: o KV cache — a que ninguém calcula

Todo token que entra na conversa deixa um rastro na memória. O modelo guarda os vetores de chave e valor de cada token, em cada camada, para não ter que recalcular a atenção do zero a cada palavra gerada. Isso é o KV cache, e ele cresce linearmente com o contexto.

A fórmula:

bytes por token = 2 × camadas × cabeças_kv × dim_cabeça × bytes_por_elemento

O 2 é porque são duas matrizes: chave e valor. Os outros três números você lê direto do config.json do modelo — num_hidden_layers, num_key_value_heads e head_dim (ou hidden_size / num_attention_heads, quando head_dim não está declarado).

Para o Llama 3 8B — 32 camadas, 8 cabeças KV, dimensão 128, em FP16:

2 × 32 × 8 × 128 × 2 bytes = 131.072 bytes = 128 KiB por token

128 KiB por token parece pouco. Multiplique por uma janela de contexto de verdade:

Camadas (modelo típico) KiB/token 4k 8k 32k 128k
32 (≈8B) 128 0,54 1,07 4,29 17,18
40 (≈12B) 160 0,67 1,34 5,37 21,47
64 (≈32B) 256 1,07 2,15 8,59 34,36
80 (≈70B) 320 1,34 2,68 10,74 42,95
KV cache em GB decimais, assumindo GQA com 8 cabeças KV, dimensão de cabeça 128 e cache em FP16 — a configuração da maioria das arquiteturas abertas atuais. Confira no config.json do seu modelo: quem tem mais cabeças KV multiplica esses números.

Um 32B com 32k de contexto reserva 8,6 GB só de cache — quase metade do que os pesos ocupam. Em 128k, o cache passa dos 34 GB e vira o item mais caro da conta, maior que o próprio modelo.

Parcela 3: o overhead do runtime

Sobra a parcela chata de estimar, porque depende do runtime, do driver e de quanto o kernel de atenção precisa de espaço temporário:

  • Contexto de CUDA: entre 300 e 600 MB, só por existir um processo usando a GPU.
  • Buffers de compute: o espaço temporário da atenção e do feed-forward, tipicamente algumas centenas de MB, proporcional ao batch e ao contexto.
  • Fragmentação do alocador: a memória disponível nunca é 100% aproveitável.

Na prática, 1 GB é uma reserva honesta para uma inferência de usuário único no llama.cpp ou Ollama. Servidores com vLLM ou TensorRT-LLM reservam bem mais, porque pré-alocam o cache inteiro na subida.

A conta fechada

Juntando as três parcelas para o caso que me interessa — um 32B em Q4_K_M com 32k de contexto:

32B · Q4_K_M · 32k de contexto

Pesos
20,1 GB
KV cache
8,6 GB
Overhead
1,0 GB
Total
29,7 GB (27,6 GiB)
Disponível
32 GiB (34,4 GB)
Folga
4,4 GiB

Cabe — mas com 4 GiB de folga, não com os 12 GB que a conta de cabeça prometia. E se você subir o contexto para 64k, não cabe mais.

Como conferir de verdade

Toda essa aritmética serve para prever. Para saber, meça — antes e depois de carregar o modelo, com a mesma janela de contexto que você vai usar de fato:

# Antes de carregar: quanto já está ocupado (compositor, navegador, etc.)
nvidia-smi --query-gpu=memory.used,memory.total --format=csv

# Carrega com a janela de contexto real, nao com a padrao
OLLAMA_CONTEXT_LENGTH=32768 ollama run qwen3:32b "ok"

# Quanto o modelo reservou de fato, e se sobrou algo na CPU
ollama ps

O ollama ps mostra uma coluna PROCESSOR. Se ela disser algo como 70%/30% CPU/GPU, parte do modelo foi para a RAM do sistema — e aí o throughput despenca por um fator de dez, porque cada token precisa atravessar o barramento PCIe.

Quando não cabe

Em ordem de custo-benefício, do que menos dói para o que mais dói:

  1. Reduza o contexto. É a alavanca mais barata e a mais ignorada. Ninguém precisa de 128k para o que faz 90% do tempo, e cada corte pela metade devolve metade do cache.
  2. Quantize o KV cache. --cache-type-k q8_0 --cache-type-v q8_0 no llama.cpp corta o cache pela metade com perda de qualidade que raramente aparece em uso normal. É a melhor troca da lista.
  3. Desça uma quantização. De Q6_K para Q4_K_M devolve uns 25% dos pesos. A degradação é real, mas costuma ser menor do que a intuição sugere.
  4. Faça offload de camadas para a CPU. Funciona, cabe quase qualquer coisa — e é dez vezes mais lento. Último recurso.
  5. Troque de modelo. Um 12B bem escolhido rodando inteiro na GPU entrega mais valor por segundo do que um 32B metade na CPU.

A ordem importa: as duas primeiras opções custam quase nada em qualidade e resolvem a maioria dos casos. A quarta é a que todo mundo tenta primeiro, e é a pior.


No próximo post eu meço o que essa conta prevê, na bancada, com número de tokens por segundo para cada configuração. A aritmética diz o que cabe; só a medição diz o que vale a pena.