Accelerate documentation
Comparando o desempenho em configurações distribuídas
Comparando o desempenho em configurações distribuídas
Avaliar e comparar o desempenho de diferentes configurações pode ser bastante complicado se você não souber o que procurar. Por exemplo, você não pode executar o mesmo script com o mesmo tamanho de lote em TPU, multi-GPU e single-GPU com Accelerate e esperar que seus resultados sejam os mesmos.
Mas por quê?
Existem três motivos para isso, que este tutorial abordará:
- Definindo as sementes corretas
- Tamanhos de Lote Observados
- Taxas de Aprendizado
Definindo a Semente
Embora esse problema não tenha surgido com tanta frequência, certifique-se de usar utils.set_seed() para definir completamente a semente em todos os casos distribuídos, para que o treinamento seja reproduzível:
from accelerate.utils import set_seed
set_seed(42)Por que isso é importante? Internamente, isso definirá 5 configurações de seed diferentes:
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed_all(seed) # or torch.xpu.manual_seed_all, etc
# ^^ safe to call this function even if cuda is not available
if is_torch_xla_available():
xm.set_rng_state(seed)O estado aleatório, o estado do numpy, o torch, o estado do dispositivo do torch e, se TPUs estiverem disponíveis, o estado cuda do torch_xla.
Tamanhos de Lote Observados
Ao treinar com Accelerate, o tamanho de lote passado ao dataloader é o tamanho de lote por GPU. Isso significa que um tamanho de lote de 64 em duas GPUs é, na verdade, um tamanho de lote de 128. Como resultado, ao testar em uma única GPU, isso precisa ser levado em consideração, assim como para TPUs.
A tabela abaixo pode ser usada como referência rápida para testar diferentes tamanhos de lote:
Neste exemplo, há duas GPUs para “Multi-GPU” e um pod de TPU com 8 workers
| Tamanho do Lote em GPU Única | Tamanho de Lote Equivalente em Multi-GPU | Tamanho de Lote Equivalente do TPU |
|---|---|---|
| 256 | 128 | 32 |
| 128 | 64 | 16 |
| 64 | 32 | 8 |
| 32 | 16 | 4 |
Taxas de Aprendizado
Conforme observado em diversas fontes[1][2], a taxa de aprendizado deve ser escalada linearmente com base no número de dispositivos presentes. O trecho de código abaixo mostra como fazer isso com o Accelerate:
Como os usuários podem ter seus próprios agendadores de taxa de aprendizado definidos, deixamos a critério do usuário decidir se deseja ou não escalar sua taxa de aprendizado.
learning_rate = 1e-3
accelerator = Accelerator()
learning_rate *= accelerator.num_processes
optimizer = AdamW(params=model.parameters(), lr=learning_rate)Você também notará que o accelerate ajusta a taxa de aprendizado com base no número de processos em treinamento. Isso se deve ao tamanho de lote observado mencionado anteriormente. Portanto, no caso de 2 GPUs, a taxa de aprendizado será ajustada duas vezes mais frequentemente do que em uma única GPU, para compensar o fato de o tamanho do lote ser o dobro (caso nenhuma alteração no tamanho do lote da instância de GPU única seja feita).
Acumulação de Gradientes e Precisão Mista
Ao usar acúmulo de gradiente e precisão mista, devido à forma como a média dos gradientes funciona (acúmulo) e à perda de precisão (precisão mista), alguma degradação no desempenho é esperada. Isso será explicitamente observado ao comparar a perda por lote entre diferentes configurações de cálculo. No entanto, a perda geral, a métrica e o desempenho geral no final do treinamento devem ser aproximadamente os mesmos.
Update on GitHub