O problema do dimensionamento manual de endpoints
Dimensionar corretamente um endpoint de IA generativa é um dos desafios mais comuns em produção. Sem uma abordagem sistemática, o processo se resume a implantar, testar manualmente com carga, ajustar e repetir — até que os números pareçam aceitáveis. O problema é que essa abordagem leva a dois extremos igualmente ruins: provisionar instâncias demais e desperdiçar orçamento em GPUs ociosas, ou provisionar de menos e ver as requisições se acumularem em fila, a latência disparar e os usuários sofrerem com degradação no serviço.
Para resolver isso, a AWS integrou os concurrency sweeps ao Amazon SageMaker AI Inference Recommendations. Trata-se de uma abordagem de benchmarking automatizado que envia níveis crescentes e controlados de tráfego simultâneo ao endpoint e analisa seu desempenho — sem nenhuma infraestrutura customizada de testes de carga para construir ou manter.
Neste artigo, a AWS documenta o processo completo: desde o deploy do modelo NVIDIA Nemotron-3 Nano 30B, passando pela execução dos concurrency sweeps automatizados, até a análise dos resultados para tomar decisões de capacidade baseadas em dados.
O que é um concurrency sweep?
Um concurrency sweep envia um número controlado de requisições simultâneas ao endpoint no SageMaker AI e mede duas métricas em cada nível:
- Throughput (vazão): quantos tokens por segundo o endpoint produz.
- Latência: quanto tempo cada requisição leva para ser processada.
Ao aumentar progressivamente a concorrência — por exemplo, de 64 para 256 e depois para 1.024 requisições simultâneas — é possível traçar uma curva que revela o ponto de saturação do endpoint. Esse é o momento em que adicionar mais tráfego simultâneo deixa de melhorar o throughput e começa a degradar a latência.
Com esses dados em mãos, a equipe obtém três informações fundamentais para o planejamento de produção:
- O equilíbrio ideal: o nível de concorrência onde o throughput é maximizado com latência ainda aceitável.
- O ponto de ruptura: onde a latência cruza o limite definido pelo Acordo de Nível de Serviço (SLA — Service Level Agreement).
- O fator de dimensionamento: quantas instâncias são necessárias para cobrir o pico de tráfego, considerando a capacidade por instância.
Visão geral da solução
O fluxo de trabalho do concurrency sweep é composto por quatro etapas:
- Implantar o modelo em um endpoint do SageMaker AI usando o container nativo vLLM.
- Configurar o perfil de carga de trabalho (contagem de tokens de entrada e saída, modo de streaming).
- Executar o concurrency sweep usando a API CreateAIBenchmarkJob.
- Analisar os resultados para identificar a concorrência ideal e dimensionar a frota.
A seguir, cada etapa é detalhada. Recomenda-se acompanhar com o notebook de exemplo disponível no repositório.
Passo a passo completo
Pré-requisitos
Antes de começar, é necessário ter:
- Uma conta AWS com acesso ao Amazon SageMaker AI.
- Uma função de execução do Gerenciamento de Identidade e Acesso da AWS (IAM — AWS Identity and Access Management) com permissões para o SageMaker AI e o Serviço de Armazenamento Simples da Amazon (Amazon S3 — Amazon Simple Storage Service).
- Cota de serviço para endpoints
ml.g7e.2xlarge.
Etapa 1: Deploy do modelo com o container nativo vLLM
O exemplo utiliza o NVIDIA Nemotron-3 Nano 30B, um modelo de Mistura de Especialistas (MoE — Mixture-of-Experts) com apenas 3B de parâmetros ativos, implantado em uma instância ml.g7e.2xlarge. Essa instância é equipada com uma GPU NVIDIA Blackwell, que oferece uma boa relação custo-desempenho para cargas de inferência.
A implantação utiliza o vLLM Deep Learning Container para o SageMaker AI, configurado por meio de variáveis de ambiente com o prefixo SM_VLLM_*:
VLLM_IMAGE = (
f"763104351884.dkr.ecr.{region}.amazonaws.com/"
f"vllm:0.19.1-gpu-py312-cu129-ubuntu22.04-sagemaker"
)
environment = {
"SM_VLLM_MODEL": "nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-BF16",
"SM_VLLM_ENFORCE_EAGER": "true", # required for Mamba-Transformer hybrid
"SM_VLLM_TENSOR_PARALLEL_SIZE": "1", # single GPU
"SM_VLLM_GPU_MEMORY_UTILIZATION": "0.85",
"SM_VLLM_MAX_MODEL_LEN": "10240",
"SM_VLLM_ENABLE_PREFIX_CACHING": "true",
"SM_VLLM_TRUST_REMOTE_CODE": "true",
}
Três configurações merecem atenção especial. O flag SM_VLLM_ENFORCE_EAGER é obrigatório porque o Nemotron-3 Nano usa uma arquitetura híbrida Mamba-Transformer que exige o modo de execução eager. A utilização de memória da GPU é definida em 0.85 para deixar margem para o crescimento do cache KV (Key-Value) sob alta concorrência. O prefix caching é ativado para melhorar o desempenho em cenários onde prompts de sistema se repetem entre requisições, aproveitando o reuso de pares chave-valor em cache.
Etapa 2: Configurar o perfil de carga de trabalho
Antes de executar qualquer teste de carga, o motor de benchmark precisa saber que tipo de tráfego simular. O perfil de carga de trabalho é definido usando a API CreateAIWorkloadConfig, conforme o notebook de exemplo.
Os parâmetros utilizados foram:
- tokenizer: ID do tokenizador do modelo, para contagem precisa de tokens.
- streaming:
True— habilita respostas em streaming (necessário para métricas de Tempo até o Primeiro Token — TTFT — Time To First Token). - prompt_input_tokens_mean: 1.024 — tamanho médio do prompt de entrada.
- output_tokens_mean: 256 — tamanho médio da resposta gerada.
A escolha de 1.024 tokens de entrada e 256 de saída é representativa de cargas de trabalho de Geração Aumentada por Recuperação (RAG — Retrieval Augmented Generation) ou sumarização. Se a aplicação usar prompts menores e respostas mais longas — como em geração de código — esses valores devem ser ajustados. O streaming é habilitado para capturar métricas de TTFT, importantes para experiências interativas onde a responsividade percebida pelo usuário importa tanto quanto o throughput bruto.
Etapa 3: Executar o concurrency sweep
Com o perfil de carga definido, o job de benchmark é criado com a API CreateAIBenchmarkJob. No cenário do notebook de exemplo, os parâmetros são:
sweep_params = {
"concurrency": [64, 256, 1024], # powers of 4
"request_count": 1024, # requests per concurrency level
}
O motor de benchmark (AIPerf) executa cada nível de concorrência de forma sequencial dentro de um único job, enviando o número total de requisições definido em request_count para cada nível. Executar os níveis de forma sequencial — e não paralela — garante que cada medição reflita uma carga isolada e limpa, produzindo estimativas estatisticamente estáveis com custos controlados. Ao final, os resultados são gravados no caminho do Amazon S3 definido em OutputConfig, em formato JSON compactado, com métricas por nível.
Etapa 4: Analisar os resultados
Após a conclusão do job, os resultados são baixados e analisados. Quatro métricas são as mais relevantes:
- Throughput (tokens de saída por segundo): ele atinge um platô ou continua crescendo?
- Latência p99 de ponta a ponta: em que ponto cruza o limite do SLA?
- Dispersão entre latência p50 e p99: um gap crescente sinaliza enfileiramento sob carga.
- Tempo até o Primeiro Token (TTFT): crítico para experiências de usuário em streaming.
Ao plotar o throughput contra a latência nos diferentes níveis de concorrência, o ponto de saturação aparece como um “joelho” na curva: o throughput se estabiliza enquanto a latência p99 sobe abruptamente. No cenário de teste documentado pela AWS, esse ponto ocorre em 256 requisições simultâneas.

Os níveis de concorrência abaixo do joelho representam a zona segura de operação. Acima dele, o endpoint está sobrecarregado e os usuários esperam. Com esse mapa de comportamento em mãos, a maioria das equipes já tem informações suficientes para tomar uma decisão de capacidade com confiança.
Indo além: busca automática de concorrência baseada em SLA
O concurrency sweep da Etapa 3 exige que os níveis a testar sejam definidos manualmente. Quando não se sabe o intervalo correto — ou quando se quer automatizar o planejamento de capacidade entre versões de modelos — a AWS oferece uma alternativa: substituir a lista fixa de concorrência por uma search recipe na mesma chamada CreateAIBenchmarkJob.
A receita max-concurrency-under-sla aceita um ou mais limites de SLA e busca a maior concorrência que satisfaz todos eles. Os parâmetros de SLA disponíveis são:
- ttft_sla_ms: tempo máximo até o primeiro token em milissegundos (p95, requer streaming).
- tpot_sla_ms: tempo máximo por token de saída em milissegundos (p95, requer streaming).
- e2e_sla_ms: latência máxima de ponta a ponta em milissegundos (p99).
- error_rate_sla: fração máxima de requisições com falha (média).
Por exemplo, para encontrar a concorrência máxima onde a latência p99 de ponta a ponta permanece abaixo de 50 segundos:
search_params = {
"search_recipe": "max-concurrency-under-sla",
"e2e_sla_ms": 50000,
"concurrency_min": 16,
"concurrency_max": 4096,
"search_max_iterations": 10,
"search_initial_points": 512,
"request_count": 1024,
}
O motor de busca usa um planejador de otimização que converge na resposta em menos iterações do que uma varredura linear. Ele começa com um intervalo amplo e vai estreitando progressivamente, avaliando apenas os níveis de concorrência necessários para identificar o limite. Isso reduz tanto o número de iterações quanto o custo total da busca. No exemplo documentado, o planejador identifica que a concorrência 320 atende ao SLA com 2.782 tokens por segundo, após constatar que a concorrência 512 viola o limite.
Combinando múltiplos SLAs
Um único limite de SLA não é suficiente para a maioria das cargas de trabalho em produção. Em experiências interativas, por exemplo, pode ser necessário controlar tanto a latência de ponta a ponta quanto o tempo até o primeiro token ao mesmo tempo. A receita max-concurrency-under-sla suporta múltiplos SLAs simultâneos:
search_params = {
"search_recipe": "max-concurrency-under-sla",
"e2e_sla_ms": 50000, # p99 end-to-end < 50s
"ttft_sla_ms": 1500, # p95 time-to-first-token < 1.5s
"concurrency_min": 16,
"concurrency_max": 4096,
"search_max_iterations": 10,
"request_count": 1024,
}
Nesse caso, ao combinar SLAs de latência de ponta a ponta e de tempo até o primeiro token, o nível máximo de concorrência suportado cai para 80 — bem abaixo dos 320 encontrados com apenas um SLA. Isso evidencia a importância de testar com múltiplas restrições quando a experiência do usuário é sensível a ambas as dimensões.
Limpeza dos recursos
Para evitar cobranças contínuas, é importante excluir os endpoints do SageMaker, as configurações de endpoint e os modelos após os testes. Endpoints são cobrados por hora, independentemente de estarem recebendo tráfego ou não.
Conclusão
Os concurrency sweeps substituem o empirismo por dados no processo de planejamento de capacidade para endpoints de IA generativa. Em vez de superprovisionamento como precaução ou descoberta de gargalos em produção, é possível mapear sistematicamente o envelope de desempenho do endpoint e tomar decisões informadas sobre o tamanho da frota antes que qualquer requisição de usuário real chegue ao sistema.
O notebook completo está disponível no repositório no GitHub. Para começar com seus próprios modelos, a AWS disponibiliza a documentação de Recomendações de Inferência de IA Generativa. Há também um exemplo que faz benchmark do GLM 5.3 Flash no Amazon SageMaker AI usando esse recurso.
Fonte
Right-size generative AI endpoints with concurrency sweeps on Amazon SageMaker AI (https://aws.amazon.com/blogs/machine-learning/right-size-generative-ai-endpoints-with-concurrency-sweeps-on-amazon-sagemaker-ai/)
Leave a Reply