Avançado

O KV cache

O decode autorregressivo armazena keys e values de attention passados; no Qwen3.8-27B apenas as 16 camadas de full attention fazem cache, a 64 KiB por token e 16 GiB por sequência de comprimento total.

Atualizada em

01 · Conceito

Conceito

Suponha que você sirva o Qwen3.8-27B e um usuário abra uma conversa que cresce em direção ao contexto nativo de 262.144 tokens do modelo. Os pesos são um custo fixo. O que não é fixo é a memória que essa conversa mantém refém enquanto está ativa — e, para dimensioná-la, você precisa saber exatamente o que é o KV cache e, para este modelo, quais camadas de fato mantêm um.

Um modelo decoder-only gera um token, anexa e repete. Uma implementação ingênua rodaria a rede inteira de novo sobre a sequência crescente a cada passo, refazendo trabalho idêntico sobre o prefixo. O KV cache armazena os estados de attention de que os tokens futuros precisam, transformando computação repetida em memória reutilizável. Numa camada de attention, cada token produz projeções de query, key e value. Durante o decode causal, apenas a posição mais nova precisa de uma saída nova: sua query dá attention às keys em cache e mistura os values em cache, enquanto as queries passadas nunca mais são necessárias. Então o cache retém keys e values passados, e o token novo computa apenas seus próprios qtq_t, ktk_t e vtv_t. Para um head,

ot=softmax(qtKtdk)Vt,o_t=\operatorname{softmax}\left(\frac{q_tK_{\leq t}^{\top}}{\sqrt{d_k}}\right)V_{\leq t},

onde as matrizes em cache crescem à medida que ktk_t e vtv_t são anexados. Isso é uma consequência da attention causal exata, não uma aproximação dela. Ignorando overhead do allocator, o modelo de memória é

  1. Cabeças KV4
  2. Dimensão da cabeça256
  3. Chaves e valores× 2
  4. bfloat16× 2 B
  5. 4 KiB por tokenpor camada

4 cabeças KV × 256 dimensões × 2 (chaves e valores) × 2 bytes = 4 KiB, para cada token, em cada camada que atende.

  1. Suposto: todas as camadas fazem cache64 camadas → 64 GiB

Multiplique pelas 64 camadas e você obtém 256 KiB por token, ou 64 GiB no contexto completo. Isso está errado: supõe que toda camada é de atenção.

  1. Camadas Gated DeltaNet48 camadas · ~144 MiB no total, constante
  2. Camadas de atenção completa16 camadas · 64 KiB por token · 16 GiB no contexto completo

Apenas 16 camadas são de atenção completa; as outras 48 são Gated DeltaNet e não fazem cache por token. Isso dá 64 KiB por token e 16 GiB no contexto completo — ao lado de um estado DeltaNet de cerca de 144 MiB que nunca cresce.

Por que apenas 16 das 64 camadas fazem cacheO cache cresce por token, mas apenas nas camadas de atenção completa. Supor que toda camada faz cache é o erro clássico, e superestima o orçamento em quatro vezes.
bytes2LTHkvDB,\text{bytes}\approx 2\,L\,T\,H_{kv}\,D\,B,

com o fator dois para keys mais values, LL camadas com cache, TT posições, HkvH_{kv} KV heads, DD head dimension e BB bytes por elemento.

Agora substitua os números do Qwen3.8-27B — com cuidado, porque existe um desvio clássico aqui. A config diz 64 camadas, 4 KV heads, head dimension 256, bf16. Por token por camada: 4×256×2×2 B=4096 B=4 KiB4 \times 256 \times 2 \times 2\ \text{B} = 4096\ \text{B} = 4\ \text{KiB}. Multiplique por 64 camadas e você obtém 256 KiB por token, e em contexto completo 256 KiB×262,144=64 GiB256\ \text{KiB} \times 262{,}144 = 64\ \text{GiB} para uma única sequência — o que, ao lado de 54 GB de pesos em bf16, encheria até a borda um acelerador de 192 GB com dois usuários e o estouraria com três. Essa estimativa está errada, e errada de um jeito instrutivo: ela supõe que toda camada é uma camada de attention.

A lição 4.16 mostrou que apenas 16 das 64 camadas são full attention; as outras 48 são camadas de Gated DeltaNet, que mantêm um estado recorrente de tamanho fixo e não fazem cache de nada por token. A derivação correta:

4 KV heads×256×2(K+V)×2 B=4 KiB por token por camada,4\ \text{KV heads} \times 256 \times 2\,(K{+}V) \times 2\ \text{B} = 4\ \text{KiB por token por camada}, 4 KiB×16 camadas com cache=64 KiB por token,4\ \text{KiB} \times 16\ \text{camadas com cache} = 64\ \text{KiB por token}, 64 KiB×262,144 tokens=16 GiB por sequeˆncia no contexto nativo completo.64\ \text{KiB} \times 262{,}144\ \text{tokens} = 16\ \text{GiB por sequência no contexto nativo completo}.

A suposição errada quadruplicou a resposta. Dezesseis gibibytes ainda é enorme — cerca de um quinto de uma placa de 80 GB para uma conversa — mas é o número real, e todo plano de capacidade das tracks 8 e 9 se apoia nele.

As 48 camadas de DeltaNet são o contraponto. A implementação de referência do Transformers mantém o estado matricial recorrente em float32: 48 value heads × 128 × 128 × 4 bytes = 3 MiB por camada, ou 144 MiB nas 48, sem contar um estado de convolução curta muito menor. Esse valor é constante no comprimento da sequência. O token um e o token 262.144 custam a mesma memória matricial. Outros runtimes podem escolher outro dtype para o estado, então confira a alocação realizada; a barganha arquitetural é o formato fixo, não um número universal de bytes.

Mesmo dentro das camadas com cache, as 4 KV heads já são uma economia: o modelo pede que 24 query heads compartilhem 4 K/V heads (grouped-query attention), encolhendo HkvH_{kv} e, portanto, o tamanho do cache e a banda do decode. A lição 7.6 compara essa escolha com MQA e MLA numericamente. Formatos de cache quantizados encolhem BB; sliding windows encolhem o TT efetivo ao preço do esquecimento.

Dimensionar é só metade da engenharia. O decode lê um histórico longo para produzir pouca computação nova, então mover dados de K/V pode dominar; os kernels precisam de layouts amigáveis enquanto as sequências crescem de forma imprevisível. Reservar antecipadamente os 16 GiB máximos de cada requisição seria ruinoso; a alocação paginada distribui blocos de tamanho fixo sob demanda no lugar disso (lição 7.8). O prefix caching compartilha blocos entre requisições que começam com exatamente a mesma sequência de tokens, como um system prompt comum — seguro somente sob o mesmo modelo, adapter e tratamento posicional, e nunca através de fronteiras de autorização.

Uma última correção à intuição: o cache não torna o decode de tempo constante em contexto. A reprojeção do prefixo desaparece, mas cada nova query nas 16 camadas de attention ainda lê e dá attention a tudo o que foi retido. O modelo durável é uma transcrição — computação já realizada vira memória, poupando aritmética ao preço de responsabilidades crescentes de banda, capacidade, ciclo de vida e privacidade — mantida, neste modelo, por apenas um quarto das camadas.

02 · Analogia

Analogia

Um estenógrafo de tribunal mantém uma transcrição indexada de tudo o que já foi dito. Quando chega uma pergunta nova, o juiz consulta a transcrição em vez de pedir que cada testemunha repita a audiência desde o começo. A transcrição cresce a cada rodada e precisa preservar a ordem exata e a identidade do processo. O KV cache é essa transcrição para a attention: as keys anteriores são as entradas do índice, os values anteriores são o depoimento guardado, e a nova query os lê.

03 · Explique de volta

Explique de volta

Derive o tamanho do KV cache de uma sequência de comprimento total do Qwen3.8-27B, dizendo explicitamente quais camadas fazem cache e quais não fazem, e contraste o resultado com o estado do DeltaNet.

Mínimo: 80 caracteres e 15 palavras. Seu texto fica somente neste navegador.

Aguardando sua explicação.

Comparar com uma resposta-modelo

Cada camada com cache armazena, por token passado, keys e values para as 4 KV heads com head dimension 256 em bf16: 4 × 256 × 2 (K e V) × 2 bytes = 4 KiB por token por camada. Só as 16 camadas de full attention fazem cache — as outras 48 camadas de Gated DeltaNet mantêm estados recorrentes de tamanho fixo — então, por token, o cache é 16 × 4 KiB = 64 KiB, e no contexto nativo de 262.144 tokens uma sequência guarda 64 KiB × 262.144 = 16 GiB. Na implementação de referência do Transformers, cada camada de DeltaNet mantém um estado matricial em float32 de 3 MiB; as 48 somam 144 MiB por sequência, constantes no comprimento e sem contar o pequeno estado de convolução.

04 · Teste seu entendimento

Teste seu entendimento

01No Qwen3.8-27B, quais camadas anexam keys e values ao cache durante o decode?
Resposta e explicação

Apenas as 16 camadas de full attention; as 48 camadas de Gated DeltaNet mantêm estado de tamanho fixo no lugar — O layout híbrido da lição 4.16 coloca uma camada de full attention a cada quatro; só essas camadas têm K/V por token para guardar.

02Aproximadamente quanta memória de KV cache ocupa uma sequência em bf16 no contexto nativo completo de 262.144 tokens do Qwen3.8-27B?
Resposta e explicação

16 GiB — 64 KiB por token × 262.144 tokens = 16 GiB; 64 GiB é a estimativa com contagem errada de camadas, 144 MiB é o estado matricial de DeltaNet em float32 da referência e 54 GB são os pesos em bf16.

Conclua o teach-back e acerte o quiz para finalizar a aula.

◎ · Marcador de evidência

Fontes

  1. Qwen Team (2026). Qwen3.8-27B Model Card.
  2. Qwen Team (2026). Qwen3.8-27B config.json.
  3. Hugging Face Transformers (2026). Implementação de referência do Qwen3.5.
  4. Woosuk Kwon et al. (2023). Efficient Memory Management for Large Language Model Serving with PagedAttention.