GPU para seus projetos · pagamento em cripto sem KYC Como alugar
Português
Abrir o console
Guia prático / KERNODECK

Mudar para precisão mista sem perder o controle numérico

Estabeleça uma referência em precisão usual, ative autocast no cálculo à frente e na perda, depois compare saídas, gradientes e qualidade nas mesmas entradas. No treinamento FP16, o GradScaler ajuda a lidar com gradientes de pequena amplitude; ele não torna todo modelo compatível. o BF16 tem um comportamento numérico diferente. Mantenha um critério explícito de reversão antes de buscar ganho de memória ou de velocidade.

7 min de leitura · Guia para desenvolvedores

Começar por uma referência que atende à necessidade

Escolha um conjunto curto com entradas comuns, casos limites e fronteiras de decisão. Fixe modelo, pesos, pré-processamento e modo train ou eval. Uma comparação entre dois modelos ou dois batches não permite atribuir sua diferença à precisão.

Registre a saída útil para sua aplicação, não apenas a perda. Para um classificador, isso pode incluir scores e decisões; para uma regressão, erro e valores extremos. Verifique desde já a presença de NaN ou de inf na referência. Uma execução FP32 incorreta não se torna uma base confiável porque possui mais bits.

Defina tolerância, qualidade mínima e ausência de não finitos antes do teste. O PyTorch lembra que o cálculo em ponto flutuante não garante resultados idênticos entre dispositivos ou caminhos de execução.

Distinguir autocast, formato numérico e GradScaler

O autocast escolhe o tipo de certas operações conforme sua política de computação. Ele não transforma todo o programa em um formato único. Com esse uso, evite converter manualmente todo o modelo por meio de half(). A documentação atual recomenda torch.autocast ou torch.amp.autocast; as interfaces antigas torch.cuda.amp estão obsoletas.

O GradScaler atua sobre a escala da perda e dos gradientes durante o treinamento. Ele não é usado como acelerador da inferência, que não realiza backward. O FP16 tem uma faixa numérica mais restrita que o BF16; um modelo projetado para BF16 pode estourar em FP16. Uma redução repetida da escala, portanto, não estabelece que o problema foi resolvido.

Escolha o formato a partir das restrições do modelo e das operações realmente utilizadas, e depois verifique o suporte do destino. O nome comercial de uma placa ou uma preferência de preparação do PyTorch não prova que seu operador personalizado possui o kernel desejado.

Role a tabela para ler todas as colunas.
Decisões de precisão a validar no projeto
EscolhaFunçãoControle necessário
Referência FP32Ponto de comparação do projetoSaídas finitas e qualidade esperada
Autocast FP16Certas operações em precisão reduzidaFaixa numérica e gradientes
Autocast BF16Outro compromisso faixa/precisãoOperadores disponíveis e qualidade
GradScalerGerenciamento da escala dos gradientesAtualizações realmente efetuadas

Colocar as etapas do treinamento na ordem correta

O trecho proposto pressupõe um modelo e um otimizador já construídos, uma entrada e um alvo na mesma GPU, e uma perda escalar. Ele não foi executado e não constitui uma validação de uma oferta. O contexto autocast envolve o forward e a perda; o backward ocorre depois de seu fechamento. O scaler é criado uma vez para a sessão de treinamento, não a cada batch.

Para inspecionar ou recortar os gradientes, primeiro remova seu fator de escala com unscale_. Os exemplos oficiais de AMP especificam fazer isso uma única vez por otimizador e após o acúmulo dos gradientes destinados à sua atualização. O limiar de recorte 1.0 abaixo é um valor ilustrativo a ser escolhido para o seu projeto, não uma recomendação universal.

As guardas interrompem aqui o diagnóstico se perda, gradientes ou norma total não forem finitos. Essas leituras de CPU são intrusivas: não cronometre este trecho. Acúmulo, múltiplos otimizadores e agendador exigem sua própria definição da atualização.

Sequência AMP pedagógica em GPU, não executada
import torch

# Pré-condições: model, optimizer, loss_fn, inputs e targets existem.
# O modelo e as entradas estão no mesmo dispositivo CUDA/HIP.
dtype = torch.float16  # Escolha a validar; BF16 é outro teste.
scaler = torch.amp.GradScaler("cuda", enabled=(dtype == torch.float16))

# Coloque no seu loop, com scaler mantido entre os batches.
optimizer.zero_grad(set_to_none=True)
with torch.autocast(device_type="cuda", dtype=dtype):
    prediction = model(inputs)
    loss = loss_fn(prediction, targets)
if not bool(torch.isfinite(loss).item()):
    raise FloatingPointError("Perda não finita: interromper o diagnóstico")
scaler.scale(loss).backward()
scaler.unscale_(optimizer)
if any(p.grad is not None and
       not bool(torch.isfinite(p.grad).all().item())
       for p in model.parameters()):
    raise FloatingPointError("Gradiente não finito: interromper o diagnóstico")
torch.nn.utils.clip_grad_norm_(
    model.parameters(), max_norm=1.0, error_if_nonfinite=True,
)
scaler.step(optimizer)
scaler.update()

Exemplo desenvolvido: duas decisões próximas não são intercambiáveis

Suponha um serviço que escolhe a classe com a pontuação máxima. Em uma entrada pedagógica, a referência produz duas pontuações muito próximas: 1,0000 e 1,0003. Outro caminho numérico poderia alterar sua ordem ou criar um empate. Esses números ilustram uma fronteira de decisão; não são saídas medidas de FP16 ou BF16.

A verificação correta tem dois níveis. Compare as pontuações com tolerâncias explícitas e depois compare a decisão e a regra aplicada aos empates. Uma diferença pequena em valor absoluto pode mudar a ação escolhida. Por outro lado, uma diferença numérica visível pode permanecer sem consequência para uma tarefa cujo limiar está longe das pontuações observadas.

Registre identificadores, saídas de referência, teste AMP e impacto na decisão. Defina a regra de aceitação antes de ler os resultados. Não amplie a tolerância para fazer desaparecer um caso incômodo; saídas de escalas diferentes podem exigir critérios distintos.

Role a tabela para ler todas as colunas.
Ficha didática de comparação, a ser completada com medições
CritérioReferênciaTeste AMPDecisão
Saídas finitasA verificarA verificarRecusar não finitos inexplicados
Desvio numéricoValores preservadosDesvio a calcularTolerância definida antes do teste
Decisão na aplicaçãoClasse ou açãoClasse ou açãoExaminar as mudanças
Qualidade no conjunto fixoA medirA medirRespeitar o limite do projeto

Interpretar os NaN e as atualizações ignoradas

Quando surgem não finitos, procure a primeira etapa que os produz: entrada, saída intermediária, perda ou gradiente. Reproduza o mesmo caso como referência e, em seguida, desative localmente o autocast em torno da operação suspeita, controlando também o tipo de suas entradas. Rodar todo um treinamento em FP32 pode servir de comparação, mas não localiza automaticamente o problema.

O scaler pode evitar uma atualização quando os gradientes contêm inf ou NaN. Um loop que continua não necessariamente realizou tantas atualizações quantas iterações. Registre esse comportamento durante o diagnóstico. Não faça avançar às cegas uma política de aprendizado que se supõe seguir as atualizações efetivas.

Uma perda finita não garante gradientes finitos. Por outro lado, um incidente pontual não basta para declarar um treinamento inutilizável: examine sua frequência, a progressão e a qualidade. A receita AMP fornece um método para isolar separadamente o autocast e o scaling quando um dos dois é suspeito.

Preparar um retrocesso reproduzível

Antes do teste, preserve a configuração de referência, os pesos, o estado do otimizador e um checkpoint coerente. Se o seu treinamento usa um scaler, o estado dele também faz parte da retomada. Documente o dtype e eventuais regiões deixadas em FP32. Retomar com uma política diferente é uma mudança experimental a ser identificada, não uma continuação implicitamente equivalente.

Volte à configuração anterior se as saídas se tornarem não finitas, se a qualidade sair do critério definido ou se as atualizações deixarem de avançar de forma aproveitável. Preserve o caso que motivou esse retorno. Após uma modificação, recomece a comparação no mesmo conjunto antes de estender a duração.

O exercício Kernodeck de checkpoints verifica uma retomada em CPU sem AMP. Reutilize o método de comparação dele acrescentando os estados realmente consumidos pelo seu loop.

Medir os ganhos somente após a validação numérica

Após a validação, meça memória e tempo sem o diagnóstico detalhado. Mantenha formas, batch, modelo e qualidade. Leituras de escalares, sincronizações e profilers podem alterar as durações; remova os controles intrusivos da medição final.

No ROCm, o nome do dispositivo PyTorch continua sendo cuda e as interfaces correspondentes são reutilizadas. Isso não garante nem os mesmos kernels nem resultados idênticos aos da NVIDIA. Verifique o backend e os operadores do projeto no alvo. Nenhuma redução fixa de memória, multiplicação de velocidade ou compatibilidade de preparação Kernodeck é anunciada por este guia.

Suas perguntas

AMP significa que todos os tensores passam para FP16?

Não. O autocast aplica uma política por operação. Algumas operações permanecem em uma precisão diferente. Converter manualmente todo o modelo para half() não é equivalente a usar autocast e pode alterar as condições de estabilidade.

BF16 sempre substitui FP16 de forma vantajosa?

Não. Os dois formatos têm compromissos diferentes, e seu suporte depende das operações e do ambiente. Compare a qualidade e o custo na sua carga; a faixa mais ampla do BF16 não garante por si só a precisão necessária.

O GradScaler é necessário para uma inferência?

O scaler atua no treinamento com gradientes, não em uma inferência sem backward. Para esta última, controle antes as saídas e a qualidade sob autocast, mantendo o modo de avaliação esperado.

Uma perda finita basta para aceitar AMP?

Não. Verifique também os gradientes, as atualizações, a qualidade e as decisões da aplicação. Uma pequena diferença numérica pode ser decisiva perto de um limiar; um treinamento que continua também pode pular algumas atualizações.