Esse é o segundo post da série onde traduzo o mundo de AI pra linguagem de engenheiros de infraestrutura. No primeiro post, mostrei que AI é só mais um workload e que suas habilidades de infra já te deixam bem mais perto desse mundo do que parece.

Agora é hora de falar do gargalo que quase todo mundo descobre tarde demais: storage.

tl;dr: GPU cara parada quase sempre significa dado chegando devagar. Pra treino de AI, storage e cache local decidem a utilização da GPU tanto quanto a placa que você comprou.

A ligação de meia-noite

Você fez tudo certo. O time de ML pediu um cluster GPU e você entregou: oito NVIDIA A100 em dois nós, rede de alta banda, drivers CUDA atualizados. Deploy impecável. O time começou o primeiro job de treinamento sexta às 18h e você foi pra casa tranquilo.

Seu celular toca à meia-noite. O lead de data science está irritado: “As GPUs não estão funcionando. O treinamento que deveria levar quatro horas nem terminou o primeiro epoch.”

Você acessa remotamente e puxa as métricas:

  • GPU utilization: 12%
  • GPU memory: um terço do total
  • Disk I/O: 100%, throughput de leitura arrastando a 60 MB/s

O time colocou 2 TB de imagens de treinamento num Azure Files Standard montado via SMB. Sua camada de storage está matando de fome o hardware mais caro do ambiente.

Essa história se repete toda semana. Times investem pesado em GPU e descobrem depois que o pipeline de dados, justamente a parte pela qual nós de infra respondemos, é o gargalo real.

Por que tudo começa com dados

Todo sistema de AI, de um classificador simples até um LLM de trilhões de parâmetros, depende da mesma conta:

Dados + Modelo + Compute = AI

Tira qualquer um dos três e não sobra nada. O ponto que muita gente demora pra enxergar é outro: dos três componentes, dados são o que encosta em infraestrutura o tempo inteiro. O modelo é código. Compute você provisiona e deixa rodando. Já os dados precisam ser ingeridos, armazenados, preparados, servidos pro treinamento e entregues na inferência. Cada etapa dessas cai no seu colo.

Conceito de infraEquivalente em AIPor que importa
Storage account / volumeRepositório de datasetOnde os dados brutos vivem antes do modelo ver
Read throughput (MB/s)Velocidade do data loaderDetermina quão rápido as GPUs recebem batches de treinamento
IOPSAmostras por segundoWorkloads com arquivos pequenos, como imagens, pedem IOPS alto
Storage tiers (Hot/Cool/Archive)Estágios do ciclo de vidaHot pra treino ativo, Cool pra datasets concluídos, Archive pra compliance
NFS/SMB mountAcesso POSIX pra frameworksPyTorch e TensorFlow esperam semântica de filesystem
Criptografia em repousoCompliance de proteção de dadosObrigatório pra PII, dados médicos e financeiros

Se você já gerencia storage, rede e controle de acesso, você entende uma boa parte do data stack de AI. O que muda é a intensidade. Workloads de AI apertam throughput de leitura, IOPS e I/O sequencial com uma força que poucas aplicações tradicionais conseguem imitar.

Data starvation: o gargalo invisível

Aqui está a parte contra-intuitiva: a causa mais comum de baixa utilização de GPU não é a GPU. É o storage.

Quando o data loader não entrega batches rápido o bastante, a GPU fica parada esperando dados. Isso se chama data starvation. Na prática, seu cluster de GPU vira um aquecedor caro.

Como diagnosticar

Se um data scientist reportar GPU utilization estranhamente baixa, olhe pro storage antes de olhar pra qualquer outra coisa. Na maioria dos casos, o problema cai em um destes cenários:

  1. Dados de treinamento em Standard HDD ou em um share Standard subdimensionado
  2. Mount remoto sem cache
  3. Cache do BlobFuse2 apontando pro disco do sistema operacional em vez do NVMe local

Sinais clássicos de data starvation:

# GPU utilization: se está abaixo de 80% durante treinamento, suspeite do storage
nvidia-smi dmon -s u -d 5

# Disk I/O: se está a 100% com GPU baixa, o padrão é bem conhecido
iostat -x 1 5

# Rede, se o dataset está remoto: throughput real vs capacidade
sar -n DEV 1 5

O padrão de diagnóstico costuma ser esse:

GPU UtilCPU UtilDisk I/ODiagnóstico
BaixaBaixaAltoData starvation: storage não entrega dados rápido o bastante
BaixaAltaBaixoPreprocessing de CPU virou gargalo
AltaAltaAltoTudo funcionando como deveria, sistema balanceado
BaixaBaixaBaixoProblema no código do modelo ou batch size mal ajustado

Regra de ouro: um ajuste de storage feito em cinco minutos pode derrubar horas do tempo total de treino. Comece por aí.

Escolhendo o storage certo: a matriz de decisão

Essa é a decisão de maior impacto na performance de um workload de AI. O mapa, em geral, é este:

StorageMelhor praThroughputLatênciaCustoNão use quando
Blob StorageDatasets, artefatos, checkpointsAté 60 Gbps por contaModerada (ms)Baixo (~$0.018/GB/mês em Hot LRS, East US, sujeito a mudança)Precisa de POSIX nativo sem mount
Data Lake Gen2Pipelines analíticos, datasets versionadosAté 60 Gbps por contaModerada (ms)BaixoWorkload simples que não precisa de ACLs granulares
NVMe localScratch de treinamento, cache do data loader3 a 7 GB/s por discoUltra-baixa (μs)Incluído na VMPrecisa de persistência: dados somem na desalocação
Azure Files (NFS)Datasets compartilhados entre nósAté 10 Gbps (premium)Baixa a moderadaModeradoWorkload single-node onde NVMe local basta
Azure Files (SMB)Compatibilidade legacy, WindowsAté 4 Gbps (premium)ModeradaModeradoTreinamento Linux de alta performance
Cosmos DBFeature stores, inferência em tempo realN/A (baseado em request)Single-digit msMais altoArmazenar datasets brutos de treinamento

O padrão de produção mais comum é uma abordagem de duas camadas: dados brutos em Blob Storage ou Data Lake Gen2 pela durabilidade e pelo custo, depois staging dos dados quentes em NVMe local pela performance.

Blob é seu warehouse. NVMe é sua bancada de trabalho.

Nunca use o hot path do treino em Standard HDD. Os limites de IOPS e throughput ficam muito abaixo do que GPUs modernas pedem. Uma A100 consegue consumir dados mais rápido do que um share Standard ou um disco Standard HDD entrega.

O padrão recomendado: Blob + NVMe + BlobFuse2

A maioria dos frameworks de ML, como PyTorch e TensorFlow, espera dados de treinamento acessíveis por um caminho de filesystem. BlobFuse2 é o driver que monta containers do Azure Blob Storage como diretório local em Linux.

O BlobFuse2 tem dois modos de cache, e aqui vale escolher com cuidado:

  • File cache: baixa o arquivo inteiro pro cache local antes de atender leituras. É o modo que faz mais sentido pra treinamento, porque o dataset costuma ser relido em múltiplos epochs.
  • Block cache (streaming): lê em blocos sem baixar o arquivo completo. Faz mais sentido pra preprocessing ou inferência em arquivos grandes.

Montar com file cache pra treinamento

# Cria diretório de cache no storage rápido local (NVMe temp disk)
sudo mkdir -p /mnt/resource/blobfuse2cache
sudo chown $(whoami) /mnt/resource/blobfuse2cache

# Cria ponto de montagem
sudo mkdir -p /mnt/training-data

# Monta com file cache
sudo blobfuse2 mount /mnt/training-data \
  --config-file=./config.yaml \
  --tmp-path=/mnt/resource/blobfuse2cache

Preload: dados prontos antes do treinamento começar

# Monta com preload: baixa dados pro cache no momento da montagem
sudo blobfuse2 mount /mnt/training-data \
  --config-file=./config.yaml \
  --tmp-path=/mnt/resource/blobfuse2cache \
  --preload

Atenção: --preload deixa o mount read-only. Pra dataset de treino isso costuma ser ótimo. Só não use esse mesmo mount no caminho onde você precisa escrever checkpoints.

Dica: aponte --tmp-path pro disco NVMe local da VM, normalmente /mnt/resource em VMs Azure com waagent, e não pro disco do sistema operacional. É ali que você consegue a menor latência possível. Em VMs da série ND, o temp disk local costuma entregar alguns GB/s de leitura.

AzCopy pra ingestão de dados em massa

Quando você precisa mover datasets grandes pro Azure, ou entre storage accounts, AzCopy costuma ser o caminho mais rápido. Ele paraleliza transferências, faz retry automático e retoma uploads interrompidos.

# Login com Microsoft Entra ID
azcopy login

# Copia um diretório inteiro de dataset pro Blob Storage
azcopy copy './local-dataset/' \
  "https://${STORAGE_ACCOUNT}.blob.core.windows.net/training-data/v1/" \
  --recursive

# Copia entre storage accounts (server-side, sem download local)
azcopy copy \
  "https://<source-account>.blob.core.windows.net/<container>" \
  "https://<dest-account>.blob.core.windows.net/<container>" \
  --recursive

Dica: use --cap-mbps quando quiser limitar throughput no horário comercial e liberar tudo à noite.

Segurança: embutida, não colada depois

Workloads de AI mexem com alguns dos dados mais sensíveis da organização: registros de clientes, imagens médicas, transações financeiras, corpora de texto proprietário.

Três regras eu trato como inegociáveis:

1. Managed identities + RBAC, sempre.

Esqueça storage account keys. São estáticas, compartilháveis e chatas de rotacionar. Managed identities ficam presas a recursos específicos, rotacionam sozinhas e ainda deixam trilha de auditoria.

# Atribui Storage Blob Data Reader pra managed identity de uma VM
az role assignment create \
  --role "Storage Blob Data Reader" \
  --assignee-object-id <managed-identity-principal-id> \
  --assignee-principal-type ServicePrincipal \
  --scope "/subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<account>"

2. Classifique antes de ingerir.

Antes de qualquer dado entrar no pipeline de treinamento, responda a pergunta chata: é público, interno, confidencial ou restrito? Sua arquitetura de storage precisa refletir isso com isolamento de rede, criptografia e controles de acesso.

3. Combata shadow data sprawl.

Data scientist adora copiar dado pra máquina local, drive compartilhado ou storage account paralela pra um “teste rápido”. Use Azure Policy pra restringir criação de storage accounts e Microsoft Purview pra localizar cópias fora dos lugares aprovados.

Mãos na massa: storage otimizado pra AI de ponta a ponta

Vamos montar um fluxo completo: provisionar, transferir, montar e validar. Todos os comandos usam --auth-mode login. Nada de storage key largada em script.

1. Cria a storage account com Data Lake Gen2

RESOURCE_GROUP="rg-ai-training"
LOCATION="eastus2"
STORAGE_ACCOUNT="staitraining$(openssl rand -hex 4)"

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

az storage account create \
  --name $STORAGE_ACCOUNT \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION \
  --sku Standard_LRS \
  --kind StorageV2 \
  --enable-hierarchical-namespace true \
  --min-tls-version TLS1_2 \
  --allow-blob-public-access false

2. Configura RBAC (sem keys)

USER_OBJECT_ID=$(az ad signed-in-user show --query id -o tsv)

az role assignment create \
  --role "Storage Blob Data Contributor" \
  --assignee-object-id $USER_OBJECT_ID \
  --assignee-principal-type User \
  --scope "/subscriptions/$(az account show --query id -o tsv)/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT"

Role assignments levam um ou dois minutos pra propagar. Espere isso antes de seguir.

3. Cria container e transfere dados

az storage container create \
  --account-name $STORAGE_ACCOUNT \
  --name training-data \
  --auth-mode login

# Pra datasets grandes, use AzCopy
azcopy login
azcopy copy './local-dataset/' \
  "https://${STORAGE_ACCOUNT}.blob.core.windows.net/training-data/v1/" \
  --recursive

4. Monta com BlobFuse2 e cache em NVMe

sudo mkdir -p /mnt/resource/blobfuse2cache
sudo chown $(whoami) /mnt/resource/blobfuse2cache
sudo mkdir -p /mnt/training-data

sudo blobfuse2 mount /mnt/training-data \
  --config-file=./config.yaml \
  --tmp-path=/mnt/resource/blobfuse2cache \
  --preload

5. Valida que o pipeline está alimentando as GPUs

# Verifica que os dados estão acessíveis
ls /mnt/training-data/v1/ | head -20

# Durante o treinamento, monitora GPU vs I/O
nvidia-smi dmon -s u -d 5 &
iostat -x 1 5

Se nvidia-smi mostrar GPU util acima de 80% e iostat não estiver batendo 100% o tempo todo, seu pipeline de dados está no caminho certo.

Checklist de saída

Antes de entregar storage pra um workload de AI:

  • A camada quente do treino usa NVMe local, Premium SSD ou cache local bem dimensionado
  • O cache do BlobFuse2 aponta pro NVMe local (/mnt/resource), não pro disco do sistema operacional
  • O acesso usa managed identity + RBAC, sem storage keys
  • Os dados foram classificados antes de entrar no pipeline
  • O storage foi pensado pra 10x o tamanho atual do dataset
  • Existem alertas de throughput e IOPS configurados
  • Os checkpoints voltam pro Blob Storage pra garantir durabilidade

Fechando o loop

Na próxima ligação de meia-noite, antes de culpar a GPU, você vai olhar pro throughput, pro cache local e pro tipo de storage. Se o disco estiver arrastando e a GPU em 12%, o problema já tem cara e sobrenome.

Leitura complementar

No próximo post

Agora que você entende como os dados fluem por um sistema de AI, e como suas decisões de storage mudam direto a performance do treinamento, faz sentido olhar pro compute que consome tudo isso. No próximo post eu vou falar sobre GPUs, famílias de VMs e arquitetura de cluster, e por que storage bem resolvido é só metade da história.

O livro completo está disponível de graça em ai4infra.com.


Esse post faz parte da série AI para Engenheiros de Infraestrutura, baseada no livro AI for Infrastructure Professionals. Novos posts toda semana.