Dimensione endpoints de IA generativa com concurrency sweeps no Amazon SageMaker AI

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.

Imagem original — fonte: Aws

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/)

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *