Avançado

Data parallelism, ZeRO e FSDP

Data parallelism compra throughput; ZeRO e FSDP distribuem parâmetros, gradientes e estado do optimizer para repartir entre ranks um orçamento de memória explicitamente assumido.

Atualizada em

01 · Conceito

Conceito

O Qwen3.8-27B é distribuído como safetensors em bf16 que totalizam cerca de 54 GB. Isso é um fato de armazenamento do checkpoint, não uma receita de memória de treino nem prova de que o stack completo de serving cabe num dispositivo nominal de 80 GB: KV cache, ativações, workspaces do runtime e fragmentação também consomem memória. O treino acrescenta categorias persistentes e transitórias cujos dtypes precisam ser declarados, não inferidos do checkpoint lançado.

A lição 9.3 assume a derivação do orçamento de memória deste modelo para todo o curso. Esta lição importa dela um cenário explícito: parâmetros e gradientes bf16, master weights fp32 e dois momentos AdamW fp32, totalizando cerca de 432 GB de estado persistente para 27 bilhões de parâmetros antes de ativações e workspaces. É uma receita conservadora comum, não uma afirmação sobre a run de treino não divulgada do Qwen nem uma exigência universal; existem políticas pure-bf16 e estados de optimizer alternativos. A aritmética de ZeRO abaixo fica condicionada a esse cenário para comparar os estágios de sharding de forma consistente.

Data parallelism é o ponto de partida e não faz nada quanto a isso. Dê a vários workers réplicas idênticas e exemplos diferentes; se o rank rr computa o gradiente grg_r, uma redução coletiva forma a média usada por toda réplica, e partir de pesos iguais com gradientes iguais os mantém sincronizados. Com PP ranks, microbatch local bb, comprimento de sequência TT e aa passos de acumulação, o batch global contém PbaTPbaT tokens — portanto adicionar workers muda a otimização, não só a velocidade. Sob replicação comum, cada rank ainda guarda todo o estado persistente assumido.

ZeRO remove a redundância em três estágios, e vale calcular o efeito num cluster concreto. Tome 64 ranks e o orçamento ilustrativo de 432 GB importado da lição 9.3.

O estágio 1 faz sharding só do estado do optimizer. Cada rank mantém parâmetros e gradientes bf16 completos, mas 1/641/64 do optimizer: 324/64=5.06324/64 = 5.06 GB. O estado persistente por rank vira 54+54+5.0611354+54+5.06 \approx 113 GB. Ainda impossível em cartões de 80 GB.

O estágio 2 também faz sharding dos gradientes: 54/64=0.8454/64 = 0.84 GB. Agora 54+0.84+5.0659.954+0.84+5.06 \approx 59.9 GB. Isso cabe — por pouco. Restam cerca de 20 GB para ativações, temporários, fragmentação e buffers de comunicação num modelo com hidden size 5120 e sequências longas, o que a lição 5.10 vai mostrar que não é muito.

O estágio 3 faz sharding dos parâmetros também, então o estado persistente é simplesmente o orçamento inteiro dividido pelo tamanho do mundo: 432/64=6.75432/64 = 6.75 GB por rank. Os parâmetros completos de um módulo existem só transitoriamente, materializados pouco antes de serem necessários.

Fully Sharded Data Parallel é esse padrão totalmente shardeado implementado em torno de módulos. Antes do forward de um módulo, os ranks fazem all-gather dos shards de parâmetro dele para reconstruir os parâmetros completos localmente; depois do uso, podem voltar a shardear. Durante o backward, a comunicação reconstrói os parâmetros de novo conforme necessário, e um reduce-scatter distribui os shards de gradiente para seus donos. Onde a ordenação e a rede permitem, essa comunicação se sobrepõe à computação.

A política de wrapping decide quão bem o estágio 3 de fato se comporta. Se a unidade shardeada for grande demais, a memória de pico do all-gather é grande e a sobreposição é limitada; pequena demais, e os coletivos ficam numerosos e a latência domina. Fronteiras de bloco de transformer são a escolha usual porque colocam compute substancial entre comunicações. Este modelo oferece uma unidade alternativa incomumente natural: suas 64 camadas são organizadas como 16 super-blocos repetidos de três camadas de Gated DeltaNet seguidas de uma camada de full attention. Fazer wrapping por super-bloco dá 16 unidades uniformes de cerca de 1,7 bilhão de parâmetros cada, o que é grosseiro mas perfeitamente balanceado; fazer wrapping por camada dá 64 unidades mais finas de dois formatos distintos. As duas opções são defensáveis, e só a medição decide.

Duas consequências operacionais decorrem disso. O checkpointing vira distribuído: um gather de state-dict completo pode exceder a memória do host, então os ranks escrevem os tensores que possuem junto com metadados que reconstroem nomes e formatos globais, e retomar com um tamanho de mundo diferente exige um formato e um loader que suportem resharding. Salvar só os pesos não basta para uma continuação exata — momentos do optimizer, posição do scheduler, loss scaler, estado do gerador de números aleatórios e cursor do data loader importam todos, e, sob a receita ilustrativa, o estado do optimizer é a maior categoria do checkpoint.

As falhas também precisam ser coletivas. Se um rank tromba com dados ruins enquanto os outros entram num all-reduce, o job trava em vez de levantar uma exceção limpa. Timeouts, propagação coordenada de erro, logs cientes de rank e identificadores reprodutíveis de batch não são luxos. A topologia de rede também molda o projeto: links rápidos dentro de um nó e links mais lentos entre nós favorecem coletivos hierárquicos, e um job de estágio 3 cujos all-gathers atravessam um tecido lento pode gastar mais tempo movendo parâmetros do que usando-os.

O modelo estável é computação replicada sobre dados diferentes, com estado cada vez mais shardeado por trás. Data parallelism compra throughput. ZeRO e FSDP removem memória redundante. Nenhum dos dois cria capacidade de graça: o preço é volume de comunicação, complexidade de escalonamento e semânticas de checkpoint e de falha muito mais exigentes.

02 · Analogia

Analogia

Várias cozinhas recebem pedidos diferentes de clientes, mas usam a mesma receita. O data parallelism comum dá a cada cozinha uma despensa completa e faz a média das correções de receita depois do serviço. O sharding divide o estoque da despensa, os cadernos de correção e até as fichas de receita entre as cozinhas; ingredientes são reunidos pouco antes de um prato e liberados depois. Cabe mais estoque coletivamente, mas o tráfego de entrega vira parte do cozinhar.

03 · Explique de volta

Explique de volta

Usando o orçamento ilustrativo de AdamW em mixed precision assumido pela lição 9.3, mostre o que cada estágio de ZeRO deixa num rank de um job com 64 GPUs e identifique quais conclusões dependem dessa receita.

Mínimo: 80 caracteres e 15 palavras. Seu texto fica somente neste navegador.

Aguardando sua explicação.

Comparar com uma resposta-modelo

A lição 9.3 deriva um orçamento ilustrativo de 432 GB de estado persistente para um modelo de 27 bilhões de parâmetros sob uma receita conservadora com parâmetros e gradientes bf16, master weights fp32 e dois momentos AdamW fp32. Essa receita é uma hipótese, não um fato publicado sobre o treino do Qwen. Data parallelism replicado mantém todo o orçamento assumido em cada rank. Em 64 ranks, ZeRO-1 distribui apenas os 324 GB do optimizer, deixando cerca de 113 GB por rank; ZeRO-2 também distribui os 54 GB de gradientes assumidos, deixando cerca de 59,9 GB; ZeRO-3 e FSDP distribuem também os parâmetros, deixando cerca de 6,75 GB de estado persistente por rank, com all-gathers transitórios. Outras receitas de dtype e optimizer mudam todos os totais, mas não a lógica do sharding.

04 · Teste seu entendimento

Teste seu entendimento

01Sob a receita ilustrativa de AdamW em mixed precision da lição 9.3, qual orçamento de estado persistente se assume para 27 bilhões de parâmetros antes das ativações?
Resposta e explicação

Cerca de 432 GB: 54 GB de pesos bf16, 54 GB de gradientes bf16 e cerca de 324 GB de master weights e momentos em fp32 — O resultado de 432 GB vem daquela receita explicitamente assumida; outros optimizers ou políticas de estado em bf16 o alteram.

02A lição 5.6 mostrou que 48 das 64 camadas são Gated DeltaNet e guardam apenas um pequeno estado de tamanho fixo na inferência. O que isso implica para a memória de treino delas?
Resposta e explicação

Nada de favorável — seus parâmetros ainda precisam de gradientes e de estado completo do AdamW, então elas fazem sharding exatamente como as camadas de attention — Os aproximadamente 144 MiB em fp32 da implementação de referência são um estado de inferência por requisição; a memória de treino é dirigida pela contagem de parâmetros e pelos momentos do optimizer, que todo tipo de camada paga por inteiro.

03O que o FSDP tipicamente faz all-gather antes de um módulo shardeado computar?
Resposta e explicação

Os parâmetros completos dele para aquela computação — Os ranks trocam shards de parâmetros just in time para que cada um possa executar a operação local de forward ou backward.

Conclua o teach-back e acerte o quiz para finalizar a aula.

◎ · Marcador de evidência

Fontes

  1. Samyam Rajbhandari et al. (2019). ZeRO: Memory Optimizations Toward Training Trillion Parameter Models.
  2. Yanli Zhao et al. (2023). PyTorch FSDP: Experiences on Scaling Fully Sharded Data Parallel.
  3. Qwen Team (2026). Qwen3.8-27B Model Card.