Como funciona

No paralelismo de dados, cada GPU recebe uma cópia idêntica do modelo e um subconjunto diferente do lote de treinamento. Cada GPU calcula gradientes independentemente. Ao fim, os gradientes são agregados (all-reduce) e os pesos atualizados de forma sincronizada.

Isso escala o throughput de treinamento linearmente com o número de GPUs, até o limite da comunicação entre elas. A sincronização pode ser síncrona (todas as GPUs esperam) ou assíncrona (atualizações independentes, menos comum hoje).

Também é possível usar acumulação de gradientes para simular lotes maiores quando a memória é limitada, processando vários mini-lotes antes de atualizar os pesos.

Exemplo prático

Treinar um modelo com 8 GPUs: cada GPU processa 1/8 do lote. Se o lote total é 256 exemplos, cada GPU vê 32. Após o forward e backward, os gradientes são somados e o modelo atualizado.

Python
import torch
from torch.nn.parallel import DistributedDataParallel as DDP

model = MyModel().to(device)
model = DDP(model, device_ids=[gpu_id])

for i, batch in enumerate(dataloader):
    loss = model(batch)
    loss.backward()
    if (i + 1) % 4 == 0:
        optimizer.step()
        optimizer.zero_grad()

Para que serve

Treinar modelos grandes em tempo viável. Sem paralelismo de dados, treinar um LLM de 70 bilhões de parâmetros em uma única GPU levaria meses. Com dezenas de GPUs, cai para semanas.

É a técnica mais simples de paralelismo e a primeira a ser aplicada quando o modelo cabe na memória de uma GPU mas o treinamento é lento.