Terceiro post da série onde traduzo AI pra linguagem de quem vive infraestrutura. No post anterior, falamos do gargalo escondido de storage. Hoje a conversa é sobre compute.

A diferença não está em comprar a GPU mais cara da prateleira. Está em escolher a GPU certa e ligar tudo do jeito certo.

tl;dr: Em AI, escolher compute é escolher workload, memória e interconexão. GPU errada ou rede errada faz você pagar caro pra terminar mais devagar.

A história que você não quer viver

O time de ML pede “um cluster GPU pra treinamento”. Você faz o que qualquer engenheiro de infra faria num primeiro impulso: provisiona oito Standard_D16s_v5. Dezesseis vCPUs cada, 64 GiB de RAM, SSD premium. No papel, parece muita coisa.

O time lança o script de treinamento. Barra de progresso: estimativa de conclusão em 47 horas. CPUs a 100%, rede mal registra tráfego e ninguém está feliz.

Aí um colega sugere dois nós Standard_ND96asr_v4, cada um com oito GPUs A100 conectadas por InfiniBand HDR de 200 Gb/s. Mesmo training job, mesmo dataset, mesmo código. O job termina em 90 minutos.

A diferença não é só ter GPU. É como elas conversam entre si dentro do nó, como sincronizam gradientes entre nós e como o dado flui sem a CPU virar gargalo. Compute pra AI é muito menos sobre força bruta e muito mais sobre combinação de hardware, topologia e rede.

Training vs. inference: dois mundos diferentes

Antes de escolher qualquer SKU, você precisa saber que workload vai rodar. Training e inference parecem parentes próximos, mas o perfil de infraestrutura muda bastante.

DimensãoTrainingInference
Padrão de workloadBatch, roda por horas, dias ou semanasOnline, respostas em milissegundos ou segundos
Demanda de GPUSatura praticamente todos os recursos disponíveisMuitas vezes roda numa GPU só, e às vezes em CPU
Pressão de memóriaGPU memory-bound (pesos, gradientes, optimizer states)Latência e bandwidth da memória costumam mandar mais do que FLOPS
Eixo de scalingScale up (GPUs maiores, mais nós)Scale out (mais réplicas atrás de load balancer)
Modelo de custoCusto total do job (horas × GPUs × preço por hora)Custo por request (latência × throughput × preço)
Impacto de falhaRestart do último checkpoint, horas perdidasRequest perdido, retry em milissegundos
Sensibilidade à redeAlta: sincronização de gradientes o tempo todoModerada: payloads menores, foco em latência

Tradução infra ↔ AI: pense em training como um job batch pesado, tipo reindexar um data warehouse gigante. Pense em inference como um endpoint de API de alta demanda. Os padrões de infra continuam sendo os mesmos. Só mudam as peças do hardware.

Quando CPU basta

Nem todo workload de AI precisa de GPU. Cenários leves de inference, como modelos pequenos de classificação, geração de embeddings pra search e deploy em edge, costumam rodar bem em VMs Standard_D ou Standard_F. Se o modelo cabe folgado na RAM e o requisito de latência passa de 50 ms, vale benchmark em CPU antes de sair queimando quota de GPU.

Dica prática: antes de provisionar qualquer coisa, pergunte ao time de ML duas coisas: (1) “estamos treinando ou servindo?” e (2) “qual o tamanho do modelo em parâmetros?” Um modelo de 350 milhões de parâmetros muitas vezes roda inference em CPU se a latência permitir. Um de 70 bilhões não.

Por que GPUs dominam AI

Uma CPU moderna de servidor tem algumas dezenas de cores otimizados pra lógica complexa e branching. Uma GPU como a NVIDIA H100 tem 16.896 CUDA cores e 528 Tensor Cores, todos desenhados pra uma tarefa muito específica: multiplicar matrizes em paralelo.

Na prática, workloads de AI passam boa parte do tempo fazendo multiplicação de matrizes. Cada camada de uma rede neural multiplica uma matriz de entrada por uma de pesos, soma um bias e aplica uma função de ativação. A CPU faz isso com poucos núcleos bem versáteis. A GPU faz milhares dessas operações ao mesmo tempo.

Tradução infra ↔ AI: pense na GPU como uma SmartNIC que descarrega do host um trabalho pesadíssimo. O CPU orquestra. A GPU faz a matemática dura.

CUDA Cores vs. Tensor Cores

Nem todos os cores de GPU são iguais:

  • CUDA cores são processadores paralelos de propósito geral, usados pra ponto flutuante e inteiros
  • Tensor Cores são unidades especializadas em operações de matriz, especialmente em precisões como FP16 e BF16

Pra workloads de AI em FP16 ou BF16, que é o normal hoje, Tensor Cores costumam ser o que mais pesa no throughput real. Quando for comparar placas, olhe além da contagem de CUDA cores.

Famílias de VMs GPU no Azure: a matriz de decisão

Escolher a família certa de VM GPU é a decisão com mais impacto no resultado do workload. Acertar significa terminar no prazo e dentro do budget. Errar significa pagar caro pra esperar mais do que precisava.

FamíliaSKU ExemploGPUsGPU MemInterconexãoMelhor Para~Custo/hr
NC T4 v3Standard_NC4as_T4_v31× T416 GiBEthernetInference custo-eficiente, light training, dev/test$0.53
NC T4 v3Standard_NC64as_T4_v34× T464 GiBEthernetMulti-model inference, batch scoring$4.35
ND A100 v4Standard_ND96asr_v48× A100 40GB320 GiB8× 200 Gb/s InfiniBandTraining distribuído, fine-tuning de modelos grandes$27.20
ND H100 v5Standard_ND96isr_H100_v58× H100 80GB640 GiB8× 400 Gb/s InfiniBandTraining de ponta, LLMs, NCCL-optimized$98.32
NV A10 v5Standard_NV36ads_A10_v51× A10 (full)24 GiBEthernetVisualização, AI leve, dev/test$3.20
NV A10 v5Standard_NV6ads_A10_v5⅙× A104 GiBEthernetGPU fracionada pra workloads pequenos$0.45
D/E/F seriesStandard_D16s_v5Nenhuma-Accelerated NetworkingPré-processamento, data pipelines, CPU inference$0.77

Preços aproximados pay-as-you-go em East US para Linux. Sempre confira no Azure Pricing Calculator.

Cuidado: a ND-series original (ND6s, ND12s, ND24s, ND24rs) foi aposentada em setembro de 2023. Se você achar template Terraform antigo ou blog post com esses SKUs, o deploy vai falhar. Pra training distribuído no Azure atual, os nomes que aparecem com mais frequência são Standard_ND96asr_v4 e Standard_ND96isr_H100_v5.

Como escolher

Pra inference: comece com Standard_NC4as_T4_v3. A T4 continua sendo um ótimo ponto de entrada: suporta INT8 e FP16, tem Tensor Cores e custa uma fração da A100. Se o modelo cabe em 16 GiB de GPU memory, eu começaria aqui.

Pra training: o tamanho do modelo manda na decisão. Fine-tuning de um modelo com menos de 10B parâmetros? Um nó Standard_ND96asr_v4 com oito A100s pode bastar. Training de modelo 70B+ do zero? A conversa já vira múltiplos nós Standard_ND96isr_H100_v5 ligados por InfiniBand, normalmente com DeepSpeed ou PyTorch FSDP.

Pra dev/test: use Standard_NV6ads_A10_v5 ou CPU pura. Não queime quota de ND-series em notebook esquecendo aba aberta.

Verifique disponibilidade antes de tudo:

az vm list-skus \
  --location eastus2 \
  --resource-type virtualMachines \
  --query "[?contains(name,'Standard_N')].{Name:name, Zones:locationInfo[0].zones, Restrictions:restrictions[0].reasonCode}" \
  -o table

Se a coluna Restrictions mostrar NotAvailableForSubscription, você provavelmente precisa pedir aumento de quota em Subscriptions → Usage + quotas.

Clustering: quando uma VM não basta

Existem três motivos clássicos pra distribuir um workload de AI: o modelo não cabe na memória de uma GPU, o training demora demais em um único nó ou a inference precisa servir mais requests do que uma VM aguenta. Cada caso leva a uma estratégia diferente.

PlataformaMelhor ParaSuporte GPUScalingComplexidade
AKSInference em escala, microservicesGPU node pools, device plugin, taintsHPA + Cluster AutoscalerMédia
Azure Machine LearningExperiment tracking, managed trainingManaged compute clusters, auto-provisioningBuilt-in, job-basedBaixa
VMSSGPU workloads homogêneos, batchCustom images com drivers pré-instaladosAutoscaling por instânciaBaixa-Média
Ray / DeepSpeed / HorovodFrameworks de training distribuídoRodam em cima de AKS ou VMsGerenciado pelo frameworkAlta

AKS pra workloads GPU

AKS é a plataforma mais comum pra servir modelos de AI em escala. Se você estiver usando GPU node pools self-managed, precisa acertar três peças: o taint no node pool, o NVIDIA device plugin e as tolerations nos pods. Se estiver usando AKS-managed GPU node pools, o AKS já instala e mantém driver, device plugin e exporter de métricas pra você.

AKS aplica um taint em pools GPU pra workloads comuns não caírem em nós caros:

sku=gpu:NoSchedule

Seus pods GPU precisam de um toleration correspondente e devem pedir GPU explicitamente:

apiVersion: v1
kind: Pod
metadata:
  name: gpu-inference
spec:
  tolerations:
  - key: "sku"
    operator: "Equal"
    value: "gpu"
    effect: "NoSchedule"
  containers:
  - name: model-server
    image: myregistry.azurecr.io/model-server:latest
    resources:
      limits:
        nvidia.com/gpu: 1

No modelo self-managed, o NVIDIA device plugin roda como DaemonSet nos nós GPU e expõe nvidia.com/gpu como recurso schedulável pro Kubernetes. Sem ele, o scheduler nem enxerga que existe GPU no nó.

Cuidado: o taint de GPU no AKS é sku=gpu:NoSchedule, não nvidia.com/gpu. Muita documentação antiga usa a key errada. O resultado é pod em Pending e perda de tempo na troubleshooting call.

Rede: o multiplicador escondido

Tem uma coisa que costuma surpreender quem chega em AI vindo de infra tradicional: a rede frequentemente vira gargalo antes da GPU. Em training distribuído, GPUs sincronizam gradientes depois de cada forward-backward pass. Com oito GPUs por nó e vários nós no cluster, isso gera dezenas de gigabytes de tráfego em poucos segundos. Se a rede não acompanha, as GPUs ficam ociosas esperando.

InfiniBand e RDMA

InfiniBand habilita RDMA (Remote Direct Memory Access). Na prática, isso permite que os dados trafeguem sem passar pelo caminho clássico de CPU + kernel, o que derruba latência e libera host pra fazer o que importa.

No Azure, InfiniBand aparece em:

  • Standard_ND96asr_v4: 8 links HDR de 200 Gb/s
  • Standard_ND96isr_H100_v5: 8 links NDR de 400 Gb/s

Pra training distribuído com NCCL, isso pode render múltiplos de throughput quando comparado com TCP/IP sobre Ethernet. Quando o ambiente está bem configurado, o NCCL usa InfiniBand automaticamente.

Accelerated Networking

Pra VMs que não têm InfiniBand, como NC-series, NV-series e boa parte das D/E/F-series, Accelerated Networking usa SR-IOV pra pular o virtual switch do host. A latência cai bastante e o throughput chega perto do limite da VM. Não custa extra. Só confira se está habilitado.

Tabela comparativa de rede

FeatureThroughputLatênciaDisponível EmUse Case
InfiniBand NDR400 Gb/s por GPU< 2 μsND H100 v5Multi-node LLM training
InfiniBand HDR200 Gb/s por GPU< 2 μsND A100 v4Training distribuído
Accelerated NetworkingAté 100 Gbps~25 μsMaioria das séries D/E/F/NInference, data pipelines
Ethernet padrãoAté 100 Gbps~500 μsTodas as VMsWorkloads gerais

Proximity placement groups

Espalhar nós de training distribuído em availability zones diferentes adiciona latência cross-zone e pode derrubar o throughput de treino. Pra jobs multi-nó, use proximity placement group sempre que a arquitetura permitir:

# Criar proximity placement group
az ppg create \
  --resource-group rg-ai-training \
  --name ppg-training-cluster \
  --location eastus2 \
  --intent-vm-sizes Standard_ND96asr_v4

# Criar VMSS dentro do proximity placement group
az vmss create \
  --resource-group rg-ai-training \
  --name vmss-training \
  --image Ubuntu2204 \
  --vm-sku Standard_ND96asr_v4 \
  --instance-count 4 \
  --admin-username azureuser \
  --generate-ssh-keys \
  --ppg ppg-training-cluster \
  --accelerated-networking true

Dica de troubleshooting: quando investigar training distribuído lento, meça a rede antes de culpar a GPU. Rode ib_write_bw entre nós. Se estiver muito abaixo do esperado, o problema costuma estar na configuração da malha, não no código do modelo.

Hands-on: crie sua primeira VM GPU

Hora de meter a mão na massa. Vamos subir uma VM GPU, instalar o driver NVIDIA e validar se a placa está viva. Vou usar Standard_NC4as_T4_v3, que é a opção mais barata pra laboratório.

Passo 0: defina variáveis

RESOURCE_GROUP="rg-ai-lab"
LOCATION="eastus2"
VM_NAME="vm-gpu-lab"
VM_SIZE="Standard_NC4as_T4_v3"
ADMIN_USER="azureuser"

Passo 1: verifique quota

az vm list-skus \
  --location $LOCATION \
  --size $VM_SIZE \
  --resource-type virtualMachines \
  --query "[].{Name:name, Restrictions:restrictions[0].reasonCode}" \
  -o table

Se mostrar NotAvailableForSubscription, peça aumento de quota no portal.

Passo 2: crie o resource group

az group create \
  --name $RESOURCE_GROUP \
  --location $LOCATION

Passo 3: crie a VM GPU

az vm create \
  --resource-group $RESOURCE_GROUP \
  --name $VM_NAME \
  --image Ubuntu2204 \
  --size $VM_SIZE \
  --admin-username $ADMIN_USER \
  --generate-ssh-keys \
  --accelerated-networking true \
  --public-ip-sku Standard

Isso provisiona uma VM Ubuntu 22.04 com uma NVIDIA T4, 4 vCPUs e 28 GiB de RAM.

Passo 4: instale drivers NVIDIA (via VM Extension)

A VM Extension é o jeito mais simples de instalar o driver certo sem ficar montando script de bootstrap na mão:

az vm extension set \
  --resource-group $RESOURCE_GROUP \
  --vm-name $VM_NAME \
  --name NvidiaGpuDriverLinux \
  --publisher Microsoft.HpcCompute \
  --enable-auto-upgrade true

Monitore o progresso, porque isso leva alguns minutos:

az vm extension show \
  --resource-group $RESOURCE_GROUP \
  --vm-name $VM_NAME \
  --name NvidiaGpuDriverLinux \
  --instance-view \
  --query "{ProvisioningState:provisioningState, Status:statuses[0].displayStatus}" \
  -o table

Passo 5: valide a GPU

SSH na VM e confirme que a GPU foi reconhecida:

ssh $ADMIN_USER@$(az vm show \
  --resource-group $RESOURCE_GROUP \
  --name $VM_NAME \
  --show-details \
  --query publicIps -o tsv)

Uma vez conectado:

nvidia-smi

Você deve ver uma Tesla T4, versão do driver e memória total próxima de 16 GiB. Se nvidia-smi retornar algo como driver ausente ou comando não encontrado, a extensão ainda não terminou de instalar.

Passo 6: limpeza

GPU VM parada custa dinheiro do mesmo jeito. Delete o resource group quando terminar:

az group delete --name $RESOURCE_GROUP --yes --no-wait

Custo real: uma Standard_NC4as_T4_v3 custa cerca de $0.53 por hora. Tranquilo pra laboratório. Já uma Standard_ND96isr_H100_v5 custa cerca de $98 por hora. Deixar uma dessas ligada por um fim de semana passa fácil de $4.700. Configure alertas de custo e políticas de auto-shutdown.

Monitorando workloads GPU

GPU infrastructure pede observabilidade própria. Métricas tradicionais de CPU não dizem quase nada sobre se a GPU está trabalhando de verdade ou esperando dado chegar.

MétricaFerramentaO que te diz
GPU utilization (%)nvidia-smi, DCGM ExporterGPU está computando ou parada?
GPU memory used (GiB)nvidia-smi, DCGM ExporterEstá perto de OOM?
GPU temperature (°C)nvidia-smi, DCGM ExporterTem thermal throttling?
Inference latency (P50/P95/P99)App Insights, OpenTelemetryExperiência do usuário e SLA
Token throughput (tokens/sec)Application logs, métricas da aplicaçãoEficiência do model serving

Setup recomendado: rode NVIDIA DCGM Exporter nos pools GPU e mande isso pra Prometheus ou Azure Managed Prometheus. Daí é Grafana, dashboard e correlação com o resto do ambiente, como qualquer outro serviço sério.

Fechando o loop

Se o time pedir “um cluster GPU” amanhã cedo, você já sabe a primeira resposta: depende do workload, do tamanho do modelo e de como essas GPUs vão conversar. Foi isso que separou as 47 horas dos 90 minutos.

Leitura complementar

No próximo post

Agora que você sabe quais VMs provisionar e como conectar tudo, faz sentido olhar dentro da GPU. No próximo post eu vou falar de hierarquia de memória CUDA, estratégias multi-GPU, stack de drivers e leitura de nvidia-smi sem chute. Você não precisa escrever CUDA kernel. Mas entender o que acontece dentro do silício te transforma num troubleshooter bem melhor.