Avançado

vLLM

Configurando um deployment real do Qwen3.8-27B: como --gpu-memory-utilization limita a alocação, por que --max-model-len precisa caber no pool de KV realizado e quais medições de startup decidem a capacidade segura.

Atualizada em

01 · Conceito

Conceito

Você tem uma GPU de 80 GB, uma cópia do Qwen3.8-27B e um pedido para levantar uma API de chat interna para talvez quarenta engenheiros. Dois números decidem se isso funciona: quanto da placa o engine pode reivindicar e quão longa uma única conversa pode ficar. Erre numa direção e o servidor se recusa a iniciar; erre na outra e ele morre na primeira rajada real de tráfego. Esta lição mostra o ciclo operacional de dimensionamento, porque todo o resto sobre o vLLM — a API no formato OpenAI, o scheduler, as métricas — é documentação que você pode ler, e confundir um teto configurado com capacidade realizada é a parte que as pessoas erram.

O vLLM existe por causa da lição 7.8. Seu scheduler admite e aposenta requisições nas fronteiras de iteração em vez de segurar um batch fixo até o membro mais lento terminar, e seu cache é paginado: blocos de tamanho fixo entregues conforme os tokens são produzidos, de modo que uma sessão que para em quatro mil tokens nunca pagou pelos trinta e dois mil que lhe eram permitidos. O trabalho do engine na inicialização é decidir de que tamanho esse pool de blocos deve ser, e ele faz isso por subtração em vez de perguntar a você.

Trate --gpu-memory-utilization como um teto, não como o pool de KV. O engine paga pesos residentes, picos de ativação, pools de CUDA graph, fragmentação do alocador e estado específico da arquitetura antes de expor qualquer capacidade de cache. A lição 9.3 é dona desse orçamento completo do acelerador, enquanto a lição 7.2 é dona da derivação de cache e estado recorrente deste modelo. Na implementação de referência, as 48 camadas Gated DeltaNet mantêm cerca de 144 MiB de estado recorrente por sequência quando esse estado está em fp32; outro runtime pode escolher dtype ou layout diferentes, portanto copiar essa contagem de bytes para uma afirmação de capacidade do vLLM sem conferir a implementação seria tão errado quanto ignorar o estado.

A fonte de verdade é, portanto, o launch que você vai servir. Fixe o checkpoint e o release do vLLM, deixe folga deliberada e leia as linhas de startup que informam o pool de KV efetivamente alocado e a concorrência máxima implicada pelo comprimento de contexto escolhido. --max-model-len precisa acomodar ao menos uma requisição dentro desse pool realizado. Se não acomodar, o engine deve rejeitar a configuração no startup; reduza o limite, mude para um formato de memória validado ou acrescente capacidade e então meça de novo.

A paginação muda a admissão depois que essa condição de segurança é satisfeita. Blocos são alocados para tokens realmente presentes, não para cada token que uma requisição tem permissão de alcançar, então conversas comuns mais curtas podem coexistir com concorrência muito maior do que sugere uma divisão pelo comprimento máximo de pior caso. Dimensione o limite rígido pela alocação realizada e depois dimensione o tráfego pela distribuição medida dos comprimentos de prompt e completion.

vllm serve Qwen/Qwen3.8-27B \
  --max-model-len 32768 \
  --gpu-memory-utilization 0.90

Não confie mais na estimativa acima do que no engine. O vLLM imprime o tamanho do pool de KV que efetivamente alocou e a concorrência máxima que isso implica no comprimento de contexto escolhido. Leia essa linha, compare com a sua aritmética e reconcilie qualquer diferença grande antes de fazer benchmark de qualquer coisa — uma discrepância normalmente significa que a reserva de workspace ou a contabilidade do estado recorrente é diferente do que você supôs.

Se o pool realizado não consegue admitir o contexto nativo completo, nenhuma flag transforma essa alocação falha em capacidade utilizável. As opções honestas são mais memória, sharding entre GPUs com tensor parallelism (lição 5.8 para a mecânica, lição 9.9 para o custo da interconexão) ou um formato de memória de menor precisão suportado pelo runtime e aprovado pelo canário de corretude da lição 8.1. Meça o novo pool realizado em vez de projetar um multiplicador a partir da largura em bits.

Leve a cadeia de medição com você, não um conjunto decorado de flags. A fração de utilização limita o engine, o log de startup informa o pool que ele efetivamente realizou e --max-model-len limita a maior reivindicação individual contra esse pool. As lições 7.2 e 9.3 são donas da aritmética por trás dessas quantidades; esta lição é dona de como o vLLM as expõe e impõe.

02 · Analogia

Analogia

O operador de um estacionamento não pergunta quantos carros existem; pergunta quantas vagas sobram depois das colunas estruturais, das rampas e do corredor de incêndio. Reservar uma vaga de comprimento máximo para cada veículo que chega, caso um deles seja um ônibus, esvazia o estacionamento. As configurações de memória do vLLM são exatamente essa conta: os pesos são as colunas, o workspace é o corredor de incêndio, e --max-model-len decide qual o comprimento máximo de vaga que um único veículo pode reivindicar.

03 · Explique de volta

Explique de volta

Explique como configurar --gpu-memory-utilization e --max-model-len para o Qwen3.8-27B sem tratar um orçamento teórico de memória como capacidade realizada, e diga o que precisa ser inspecionado antes de admitir tráfego.

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

Aguardando sua explicação.

Comparar com uma resposta-modelo

--gpu-memory-utilization é um limite superior para todas as alocações de device do vLLM, não a promessa de um tamanho de pool de KV. A lição 7.2 é dona da derivação de cache e estado recorrente do Qwen3.8-27B, incluindo os cerca de 144 MiB de estado DeltaNet por sequência quando a implementação de referência o mantém em fp32; a lição 9.3 é dona do orçamento completo do acelerador. Um release de serving pode usar outro dtype ou layout de estado e reserva memória dependente da versão e da carga para ativações, grafos e fragmentação. Comece com folga deliberada, leia no runtime exato as linhas do pool de KV realizado e da concorrência máxima e só fixe --max-model-len num valor que o pool medido consiga admitir ao menos uma vez. A paginação então faz sessões típicas mais curtas consumirem apenas os blocos que realmente usam.

04 · Teste seu entendimento

Teste seu entendimento

01Pela lição 7.8, por que a paginação permite a um servidor admitir muito mais sessões do que a aritmética de comprimento máximo sugere?
Resposta e explicação

Os blocos são alocados conforme os tokens são produzidos, então uma sessão que usa 4K de um limite de 32K paga por 4K — Reservar o máximo de cada requisição é exatamente o desperdício que o PagedAttention remove; o limite delimita uma sessão, ele não a cobra antecipadamente.

02Por que subir --gpu-memory-utilization para 0.98 a fim de aumentar o pool de KV tende a sair pela culatra?
Resposta e explicação

A fração precisa cobrir também picos de ativação, pools de graph capture, fragmentação e a diferença entre GB e GiB, então o engine fica sem memória durante o warm-up ou sob uma rajada — A fração de utilização é um orçamento para tudo que o engine aloca, não só para o cache; os últimos poucos por cento são a folga que impede um pico de tráfego de virar um out-of-memory.

03Quais camadas do Qwen3.8-27B contribuem para o pool de KV paginado?
Resposta e explicação

Apenas as 16 camadas de full attention, a 4 KiB por token cada; as 48 camadas DeltaNet guardam um estado de tamanho fixo — A lição 7.2 derivou 64 KiB por token a partir de 16 camadas que cacheiam; as camadas recorrentes custam uma constante por sequência em vez de um custo por token.

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

◎ · Marcador de evidência

Fontes

  1. vLLM Project (2026). vLLM Documentation.
  2. Woosuk Kwon et al. (2023). Efficient Memory Management for Large Language Model Serving with PagedAttention.
  3. Qwen Team (2026). Qwen3.8-27B Model Card.