Continuous batching e PagedAttention resolvem problemas diferentes no atendimento de modelos de linguagem: o primeiro organiza quais requisições avançam em cada etapa; o segundo organiza a memória usada pelo histórico de atenção. No vLLM, essa combinação ajuda a atender sequências com tamanhos variados sem depender de um lote fixo que só termina quando a resposta mais longa acaba.
Para operar o servidor, a consequência prática é equilibrar concorrência, memória de contexto e prazo de resposta. Aumentar um limite de lote não cria capacidade ilimitada. O ajuste correto depende do modelo, da GPU, dos comprimentos de entrada e saída e da distribuição real de requisições.
Resumo rápido
- Continuous batching permite renovar o conjunto de sequências durante a geração.
- PagedAttention usa blocos de KV cache sem exigir uma região física contínua por sequência.
- Pesos do modelo e KV cache disputam a memória disponível com outras estruturas do motor.
- Limites de sequências e tokens por iteração controlam dimensões diferentes do trabalho.
- Meça fila, preempções, latência e respostas concluídas antes de aceitar uma configuração.
1. Por que um lote fixo desperdiça oportunidades
Na geração de texto, uma solicitação pode terminar com uma classificação curta enquanto outra continua produzindo um relatório. Imagine um lote de três tarefas, A, B e C. Quando A termina, um sistema que aguarda todo o lote antes de renová-lo deixa de aproveitar a oportunidade de colocar a tarefa D naquele ciclo de atendimento.
Continuous batching, ou formação contínua de lotes, atualiza esse conjunto ao longo da execução. Sequências concluídas saem; outras podem entrar conforme o escalonador encontra orçamento de processamento e memória. A unidade relevante deixa de ser apenas o lote fechado de requisições recebido pelo cliente.
Isso não significa que toda requisição recém-chegada será atendida imediatamente. Existe fila, existe limite de trabalho por etapa e pode faltar espaço para o estado da nova sequência. A ideia é permitir decisões mais frequentes, e não eliminar as restrições físicas do servidor.
Para quem compra infraestrutura, a pergunta útil é quantas tarefas completas o sistema entrega dentro do prazo da aplicação. Uma utilização de GPU alta pode coexistir com usuários esperando demais. Antes de escolher parâmetros, descreva separadamente o atendimento interativo e o processamento que pode esperar.
2. KV cache: a memória que cresce com o contexto
KV cache é o armazenamento de chaves e valores calculados pelas camadas de atenção. Durante a geração autoregressiva, o modelo aproveita esse estado para continuar a sequência sem recalcular todo o passado a cada token. O cache pertence ao trabalho em andamento e cresce conforme mais posições precisam ser mantidas.
O tamanho não depende apenas de quantos parâmetros existem no modelo. Também entram arquitetura da atenção, quantidade de camadas, precisão dos valores e quantidade de tokens mantidos. Para entender por que diferentes arquiteturas pressionam a memória de maneiras distintas, veja o guia de MHA, GQA e MQA.
Um modelo que cabe na GPU em uma execução curta pode enfrentar pressão de memória quando atende vários contextos longos. Os pesos continuam presentes e agora precisam coexistir com estados de múltiplas sequências. Também existem buffers, estruturas do motor e demais alocações que impedem tratar toda a VRAM como cache livre.
Use a janela de contexto como parte do planejamento da aplicação. Permitir um contexto enorme por conveniência afeta o perfil de uso que você precisa suportar. Defina limites de entrada e saída coerentes com a tarefa, sem pressupor que todo cliente usará somente mensagens curtas.
3. O que PagedAttention muda na alocação
O trabalho original do vLLM apresenta PagedAttention como uma organização inspirada em paginação de memória virtual. O KV cache de uma sequência é dividido em blocos lógicos, associados a blocos físicos por uma tabela. Esses blocos físicos não precisam ocupar endereços consecutivos.
Uma analogia útil é uma coleção de caixas numeradas. O histórico lógico continua em ordem, mas as caixas podem estar em posições diferentes do depósito. A tabela informa onde buscar cada parte. Assim, a sequência pode receber mais blocos conforme cresce, em vez de depender de uma grande faixa contínua reservada antecipadamente.
Isso reduz dificuldades de fragmentação na organização descrita pelo projeto. Ainda pode haver espaço não utilizado no último bloco parcialmente preenchido. Não confunda organização eficiente com ausência absoluta de desperdício, nem com aumento da memória física disponível.
A documentação de design alerta que sua página sobre o kernel original é histórica e não descreve integralmente o código atual. Portanto, use o artigo e o texto original para compreender o princípio; consulte a versão instalada e seu backend para decisões de implementação. Não copie detalhes antigos do kernel como se fossem invariantes de toda instalação atual.
| Mecanismo | Decisão principal | Problema tratado | Limite que permanece |
|---|---|---|---|
| Continuous batching | Quais sequências avançam na etapa | Rigidez de lotes com durações diferentes | Orçamento de processamento e fila |
| PagedAttention | Onde ficam blocos do estado de atenção | Organização e fragmentação do KV cache | Capacidade física e blocos disponíveis |
| Limites da aplicação | Quanto trabalho admitir | Demandas incompatíveis com o serviço | Necessidade de rejeitar ou adiar excesso |
O reaproveitamento de prefixos entre requisições é outro assunto. Este guia mantém o foco na relação entre memória e escalonamento de tarefas, sem usar hits de cache como explicação para qualquer melhora observada.
4. Prefill, decode e a disputa pelo próximo passo
Prefill é o processamento inicial da entrada. Decode é a continuação que produz novos tokens. Uma requisição com documento longo traz muito trabalho inicial; uma resposta extensa continua ocupando etapas depois desse início. Misturar esses perfis torna o escalonamento mais delicado do que simplesmente contar usuários conectados.
O guia de otimização do vLLM descreve chunked prefill, que divide o processamento de entradas grandes em partes. Na arquitetura V1 documentada, quando esse recurso pode ser habilitado, o escalonamento prioriza decode e usa o orçamento restante para prefill. Essa explicação depende da arquitetura e da configuração; confirme o comportamento na versão implantada.
Como recomendação de operação, compare pelo menos três perfis: mensagens curtas, documentos longos e tráfego misto. Uma configuração que funciona bem quando todas as entradas são parecidas pode prejudicar conversas durante a chegada de documentos maiores. A mistura precisa representar seu produto.
Observe também quanto os clientes pedem de saída. Permitir relatórios extensos no mesmo serviço de classificação pode prolongar a ocupação das sequências. Se os prazos de negócio forem diferentes, considere filas ou serviços separados como hipótese a testar. Isso é uma escolha de arquitetura da aplicação, não uma obrigação imposta por PagedAttention.
5. Ajuste os limites com uma hipótese de cada vez
Na referência de linha de comando, max_num_seqs limita as sequências processadas em uma iteração, enquanto max_num_batched_tokens limita os tokens processados por iteração. Eles não são sinônimos. Duas cargas com o mesmo número de requisições podem exigir quantidades muito diferentes de trabalho.
Faça primeiro um inventário: versão do vLLM, modelo e revisão usados, GPU, memória disponível e parâmetros de inicialização. Leia a ajuda instalada. As opções e os valores padrão evoluem; a documentação consultada hoje não substitui a conferência no ambiente onde o comando será executado.
vllm --version
vllm serve --help
O comando a seguir é um ponto de partida ilustrativo para um ambiente Linux já compatível. MODELO_LOCAL deve apontar para um modelo suportado, disponível e previamente validado. Os números representam escolhas de teste, sem promessa de desempenho nem garantia de que a configuração cabe no seu hardware.
vllm serve "$MODELO_LOCAL" \
--host 127.0.0.1 \
--port 8000 \
--max-model-len 4096 \
--max-num-seqs 8 \
--max-num-batched-tokens 4096 \
--gpu-memory-utilization 0.80
O endereço de loopback restringe o acesso ao próprio host. Caso o produto precise de acesso remoto, configure a camada de rede, autenticação e controle de admissão antes de expor o serviço. Não transforme o exemplo de inicialização em endpoint público sem esse desenho.
Rode a configuração de referência até concluir o conjunto de casos. Depois altere somente um limite. Registre duração de fila, tempo de resposta, erros, conclusão e memória observada. O roteiro de avaliação de latência em produção complementa a análise das métricas; aqui a pergunta é qual mecanismo explica a mudança.
O guia de otimização informa que preempções podem ocorrer quando falta KV cache: requisições são interrompidas e seu trabalho pode ser recomputado. Isso tem custo de latência. Se aumentá-las fizer crescer o volume bruto, verifique também o impacto nos prazos individuais antes de considerar o ajuste vantajoso.
Faça uma ficha de decisão para cada experimento. Inclua hipótese, parâmetro alterado, conjunto de entradas e condição de aprovação. Por exemplo: reduzir sequências simultâneas pode aliviar pressão de cache, mas também pode aumentar espera na fila. A decisão só fica clara ao observar as duas pontas do atendimento.
Registre ainda o que aconteceu com requisições canceladas e saídas interrompidas. Uma tarefa abandonada não equivale a uma resposta útil entregue. Para comparar configurações, use a mesma regra de contagem e mantenha os cancelamentos visíveis, evitando que uma execução pareça eficiente apenas porque concluiu menos trabalho.
Exemplo: atendimento de uma distribuidora em Joinville
Imagine uma distribuidora de peças em Joinville que mantém um modelo local para consultar descrições técnicas e preparar respostas internas. O cenário é ilustrativo. Há perguntas curtas sobre compatibilidade e pedidos maiores que incluem trechos de manuais. A equipe precisa atender o balcão sem deixar o processamento documental ocupar toda a capacidade.
Ela separa um conjunto sintético de perguntas rápidas e outro de documentos. Mantém modelo, hardware e tamanho máximo de saída constantes. Primeiro observa cada grupo isolado; depois reproduz uma mistura com horários de chegada definidos. Assim, identifica se o problema nasce do contexto longo ou da convivência entre perfis.
Se a fila cresce enquanto o cache está pressionado e há preempções, aumentar indiscriminadamente a concorrência é uma hipótese fraca. O time testa um teto menor de sequências, compara conclusão por tipo de tarefa e verifica se a espera continua aceitável. Se o gargalo estiver no prefill, investiga o orçamento de tokens por etapa.
Uma configuração somente é adotada se preservar a qualidade das respostas e cumprir o prazo interno acordado. Não há resultado de benchmark neste exemplo. O relatório registra condições, limitações e observações, permitindo que outra pessoa repita o experimento quando o modelo ou a máquina mudar.
Erros comuns
- Confundir batch contínuo com fila infinita: o motor ainda precisa de política para excesso de demanda. Defina o comportamento do cliente e da camada de admissão.
- Contar somente requisições: inclua comprimentos de entrada e saída para explicar pressão de memória e processamento.
- Tratar paginação como compressão: o mecanismo organiza blocos; não autoriza assumir que qualquer contexto cabe na GPU.
- Copiar um benchmark de outro ambiente: versão, hardware e mistura de tarefas alteram o resultado. Execute seu conjunto e publique as condições.
- Elevar a utilização de memória sem margem: considere outras alocações e processos presentes no host. Uma inicialização bem-sucedida não prova estabilidade sob carga.
- Otimizar só tokens por segundo: avalie respostas úteis concluídas e prazo por grupo de tarefa, mantendo erros visíveis.
Perguntas frequentes
Continuous batching precisa de prompts iguais?
Não. O mecanismo trata a composição do conjunto em execução. A semelhança entre entradas pode importar para outras otimizações, mas não é a definição de formação contínua de lotes.
PagedAttention elimina falta de memória?
Não. A organização em blocos melhora o gerenciamento descrito pelo projeto, mas pesos, estados e estruturas do servidor continuam limitados pela capacidade disponível. Contextos e concorrência precisam de limites.
Aumentar max_num_seqs sempre acelera o serviço?
Não há essa garantia. Mais sequências competem por recursos. Teste a alteração com a mesma carga e examine fila, conclusão, erros e latência, sem inferir melhora a partir de um único indicador.
Preciso programar PagedAttention manualmente?
Para operar o vLLM, o trabalho habitual é escolher uma instalação compatível e configurar o motor. Implementar ou alterar kernels pertence a outro nível de desenvolvimento e exige verificar o backend efetivamente usado.
Qual configuração é a melhor para uma pequena empresa?
A que atende sua tarefa dentro do prazo e da capacidade contratada, com complexidade que a equipe consegue operar. Comece com limites conservadores e amplie mediante evidência do próprio ambiente.
Fontes e leitura recomendada
- vLLM: apresentação original de PagedAttention
- Artigo original: Efficient Memory Management for Large Language Model Serving with PagedAttention
- vLLM: design histórico e ressalva sobre implementação atual
- vLLM: preempção, chunked prefill e otimização
- vLLM: referência oficial de serve e limites do escalonador