GPU para pesquisa ML · Pagamento crypto sem KYC
IteraGPU
Treinamento · Memória e otimização

Reduzir o microbatch sem perder a contagem das atualizações.

A acumulação soma as contribuições de várias passagens para trás antes de uma atualização dos parâmetros. Com microbatches iguais, o batch efetivo conta o microbatch por réplica, o número de passagens acumuladas e as réplicas de dados participantes. Reduzir o microbatch pode aliviar as ativações conservadas, mas não elimina nem os pesos nem os estados do otimizador e não garante um treinamento idêntico.

01 /

Separar microbatch, passagem para trás e atualização

O microbatch é o grupo de exemplos processado por uma passagem para frente em uma réplica. A passagem para trás calcula sua contribuição aos gradientes. A atualização do otimizador usa os gradientes disponíveis para modificar os parâmetros. Com acumulação, várias passagens para frente/para trás precedem essa atualização; os parâmetros permanecem inalterados durante o grupo.

No PyTorch, os gradientes se acumulam nos tensores previstos para isso. Zerar os gradientes após cada microbatch anularia, portanto, a acumulação desejada. Por outro lado, esquecer de zerá-los entre dois grupos faria com que exemplos da atualização anterior contribuíssem.

Defina sua unidade de registro: número de microbatch, atualização do otimizador, exemplos ou tokens vistos. A palavra “step” sozinha é ambígua. Uma curva de perda não se compara corretamente se o eixo representa oito vezes mais exemplos em um dos experimentos.

Fontes técnicas: PyTorch — acumulação e zeragem dos gradientes

02 /

Calcular o batch efetivo sem contar duas vezes as GPU

Denotemos m o número de exemplos por microbatch e por réplica, A o número de microbatches acumulados, D o número de réplicas de paralelismo de dados. Se esses tamanhos forem constantes e os exemplos estiverem corretamente distribuídos, o número de exemplos que contribuem para uma atualização global é m × A × D.

O fator D não designa necessariamente todas as placas da máquina. GPU que compartilham um mesmo modelo por paralelismo de tensor ou de pipeline não se tornam tantas réplicas de dados. Registre os grupos realmente configurados, não simplesmente a quantidade comercial do lote.

Exemplo aritmético: dois exemplos por microbatch, oito acumulações e duas réplicas resultam em 32 exemplos por atualização global. Cada réplica processa dezesseis exemplos nesse grupo. A tabela compara contagens; ela não classifica sua memória ou velocidade.

Batch efetivo em exemplos = microbatch por réplica m × acumulações A × réplicas de dados D
Contagens ilustrativas, sem medição de desempenho; microbatches completos e exemplos distribuídos.
mADExemplos por atualização global
28232
116232
44232
28116

Fontes técnicas: PyTorch — batch efetivo e acumulação em precisão mista · PyTorch — comportamento das réplicas do DistributedDataParallel

03 /

Normalizar a perda de acordo com os elementos realmente avaliados

Para uma perda média em microbatches contendo o mesmo número de elementos relevantes, dividir cada contribuição por A resulta na média do grupo. Essa regra pressupõe que o framework já não faça essa normalização. Com uma ferramenta que gerencia a acumulação, releia seu contrato antes de adicionar uma divisão manual.

Para uma perda média por token, comprimentos diferentes alteram o denominador. É preciso relacionar a soma das perdas aos tokens efetivamente supervisionados do grupo, excluindo padding e posições ignoradas. A média das médias de microbatches geralmente não produz o mesmo objetivo.

Exemplo teórico: um microbatch tem 512 tokens supervisionados com uma perda média de 2; outro tem 1.536 com uma média de 4. A média ponderada é (512 × 2 + 1.536 × 4) ÷ 2.048 = 3,5. A média não ponderada é 3 e superestima o grupo pequeno. Esses valores ilustram apenas o cálculo.

Fontes técnicas: Hugging Face Accelerate — acumulação com exemplos de tamanhos variáveis

04 /

Organizar um grupo completo de acumulação

Prepare primeiro as fronteiras do grupo e seu denominador. Para cada microbatch, calcule a saída, a perda normalizada e o passo backward sem atualização intermediária. Libere as saídas das quais você não precisa mais; manter perdas ligadas ao seu grafo em uma lista pode prolongar a vida das alocações.

Após a última contribuição, aplique as operações previstas sobre o gradiente completo, depois a atualização. Em seguida, redefina os gradientes para o próximo grupo. Se a passagem terminar com menos de A microbatches, escolha explicitamente tratar esse grupo parcial com seu denominador real ou descartá-lo; registre os exemplos afetados.

Com precisão mista usando GradScaler, o fator de escala permanece constante durante a acumulação. A reescalonagem real e um eventual clipping ocorrem após as contribuições; a atualização do scaler segue a tentativa de passo. As verificações de valores não finitos podem impedir a modificação dos parâmetros.

O scheduler deve seguir a unidade anunciada pela sua iteração. Se ele for definido por atualização do otimizador, chamá-lo a cada microbatch alteraria o cronograma. Registre separadamente as tentativas e as atualizações realmente aplicadas quando o seu sistema puder pular algumas.

Fontes técnicas: PyTorch — grafos autograd e tensores mantidos para backward · PyTorch — acumulação, unscale, clipping e GradScaler

05 /

Em multi-GPU, verificar a redução e a distribuição dos exemplos

O DistributedDataParallel sincroniza os gradientes entre réplicas. Em seu comportamento usual, a redução os calcula como média; assim, uma perda somada e uma perda com média local não têm a mesma escala. Com números de tokens diferentes entre as réplicas, o denominador global e essa redução devem ser considerados em conjunto.

Verifique os IDs realmente processados: duplicar involuntariamente os mesmos exemplos em todas as placas não aumenta proporcionalmente a informação do grupo. Para atrasar as comunicações intermediárias, no_sync pode ser usado nos microbatches que antecedem a sincronização final; seu contexto deve abranger também o passo forward.

Não generalize essa regra para todos os sistemas distribuídos. Sharding de estados, pipeline, hooks de comunicação e frameworks podem alterar as operações efetivas. Comece pela configuração suportada pela sua ferramenta e depois verifique um grupo completo em cada réplica.

Fontes técnicas: PyTorch — redução de gradientes e escopo de no_sync no DDP

06 /

Por que o mesmo batch efetivo não garante a mesma experiência

A igualdade m × A × D é uma contagem. Para recuperar um gradiente de grande batch, são necessárias, entre outras coisas, contribuições corretamente ponderadas, o mesmo estado dos parâmetros durante o grupo e operações compatíveis com essa decomposição. A proximidade numérica verifica-se com uma tolerância adequada; não se deduz apenas do produto.

O BatchNorm calcula estatísticas a partir das entradas da sua passagem: vários microbatches pequenos não lhe apresentam os mesmos grupos que um grande batch. As operações aleatórias, a ordem dos cálculos e os arredondamentos também podem variar. Não prometa pesos finais idênticos bit a bit.

Uma mudança de batch global também pode alterar o número de atualizações para um mesmo número de exemplos vistos. Fixe com antecedência o eixo de comparação e a sua regra de qualidade. Não altere simultaneamente a taxa de aprendizagem, o scheduler e a duração sem documentar essas novas hipóteses.

Fontes técnicas: PyTorch — estatísticas de BatchNorm1d · PyTorch — limites de reprodutibilidade

07 /

Controlar a memória e decidir o próximo passo

Instrumente um grupo incluindo as passagens para trás e a primeira atualização, depois os grupos seguintes. Um sucesso no forward não valida os gradientes ou os estados criados pelo otimizador. Os contadores devem manter o seu âmbito por device. O dossiê de memória fornece o método de leitura das baselines e picos.

Se um grupo falhar, reduza o microbatch e recalcule A para conservar o batch efetivo pretendido, quando essa escolha continuar a ser pertinente. Essa modificação não garante nem uma divisão proporcional do pico nem uma melhor duração. Se os pesos ou os estados dominarem, a acumulação por si só pode ser insuficiente.

Antes de uma campanha, controle uma atualização num pequeno conjunto controlado: mesmos exemplos, perda ponderada, gradientes finitos, fronteira de grupo e número de passos. Depois avalie a qualidade com o protocolo escolhido. O pequeno MLP de inferência do dossiê para download não executa esta receita de treino; não substitui esse controlo.

A sua ficha final reúne m, A, D, os tokens supervisionados, a precisão, a normalização, o tratamento do último grupo e os picos observados. Volte depois à escolha de configuração e ao orçamento de experiências, separando preparação, ensaios e resultados realmente aceites.

  • Perda anormalmente pequena: procurar uma dupla divisão pela acumulação.
  • Resultado que varia com a divisão: verificar tokens ignorados e média das médias.
  • Acumulação sem efeito: controlar zero_grad e optimizer.step.
  • Memória crescente: procurar as referências mantidas entre microbatches.
  • Calendário desfasado: distinguir passagens para trás e atualizações.

Fontes técnicas: Hugging Face — picos de memória de um treino

Perguntas práticas

Acumular dezasseis microbatches multiplica a memória por dezasseis?

Não necessariamente: as contribuições são processadas sucessivamente. Os gradientes persistem, enquanto as ativações inúteis podem ser libertadas. O pico depende, no entanto, do modelo, das referências mantidas e dos estados do otimizador; meça o grupo completo.

Duas GPU duplicam sempre o batch efetivo?

Apenas se essas GPU participarem como duas réplicas de dados com o microbatch anunciado. Placas que partilham um mesmo modelo não constituem automaticamente duas réplicas. Verifique os grupos distribuídos e os exemplos processados.

Posso dividir todas as perdas pelo número de acumulações?

Essa regra simples corresponde a microbatches de peso igual, sem normalização já gerida pelo framework. Com números variáveis de tokens supervisionados ou um último grupo incompleto, use o denominador real do objetivo.