LeRobot documentation

Treinamento Multi-GPU

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.7.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Treinamento Multi-GPU

LeRobot treina em múltiplas GPUs por meio do Hugging Face Accelerate. Três layouts de paralelismo de dados são suportados:

LayoutO que ele fazConfig
DDPReplica o modelo completo em cada GPUpadrão em qualquer inicialização multi-GPU
FSDPFragmenta parâmetros, gradientes e estado do otimizador entre GPUs--parallelism.dp_shard=N
HSDPShards dentro de grupos de GPUs, replicado entre grupos--parallelism.dp_replicate=R --parallelism.dp_shard=S

Instalação

accelerate está incluído no extra training:

pip install 'lerobot[training]'

Lançamento

O treinamento distribuído pode ser iniciado tanto por meio de torchrun quanto de accelerate launch. O Accelerate é usado como um lançador simples: ele não gerencia a configuração do treinamento, e todas as configurações de treinamento distribuído ficam no próprio sistema de configuração do LeRobot.

Com torchrun:

torchrun --nproc-per-node=2 $(which lerobot-train) \
  --dataset.repo_id=${HF_USER}/my_dataset \
  --policy.type=act \
  --policy.repo_id=${HF_USER}/my_trained_policy \
  --output_dir=outputs/train/act_multi_gpu \
  --job_name=act_multi_gpu \
  --trackio.enable=true

Com accelerate launch (como um lançador simples):

accelerate launch --num_processes=2 $(which lerobot-train) \
  --dataset.repo_id=${HF_USER}/my_dataset \
  --policy.type=act \
  --policy.repo_id=${HF_USER}/my_trained_policy \
  --output_dir=outputs/train/act_multi_gpu \
  --job_name=act_multi_gpu \
  --trackio.enable=true

Sem as flags --parallelism.*, uma inicialização multiprocessos executa DDP simples. Execuções multinó utilizam as flags padrão torchrun --nnodes/--node-rank/--rdzv-endpoint (ou accelerate launch --num_machines/--machine_rank/--main_process_ip).

Os arquivos de configuração YAML do Accelerate (accelerate launch --config_file some.yaml, accelerate config) não são suportados. Eles configuram o engine por meio de variáveis de ambiente, contornando o sistema de configuração do LeRobot, de modo que train_config.json deixaria de descrever as configurações efetivamente usadas em uma execução. Por isso, lerobot-train se recusa a iniciar quando variáveis de ambiente do accelerate estão definidas. Coloque as configurações nas flags --parallelism.* / --accelerator.* em vez disso, ou defina LEROBOT_ALLOW_ACCELERATE_ENV=1 para reconhecer a substituição e prosseguir mesmo assim.

Semântica de lote, taxa de aprendizado e passos

Cada um dos dp_replicate × dp_shard workers de paralelismo de dados carrega seu próprio micro-lote --batch_size a cada passo, de modo que um passo de treinamento consome batch_size × dp_world_size amostras, e × gradient_accumulation_steps delas entram em cada atualização do otimizador:

effective_batch_size = batch_size × dp_world_size × gradient_accumulation_steps

O banner de treinamento imprime essa fatoração na inicialização. --steps conta os passos do loop (micro-lotes por worker), não as atualizações do otimizador.

A acumulação de gradiente é uma flag de primeira classe:

torchrun --nproc-per-node=2 $(which lerobot-train) \
  --batch_size=8 --accelerator.gradient_accumulation.steps=4 ...

O LeRobot não escala automaticamente a taxa de aprendizado ou o número de etapas quando o tamanho efetivo do lote aumenta. Se você escalar para mais GPUs e quiser um treinamento equivalente, ajuste manualmente, por exemplo, com 2 GPUs: dobre --optimizer.lr (escala linear) ou reduza --steps pela metade.

Treinamento fragmentado (FSDP)

Se um modelo for grande demais para treinar com DDP, faça o sharding dele com FSDP2:

torchrun --nproc-per-node=4 $(which lerobot-train) \
  --dataset.repo_id=${HF_USER}/my_dataset \
  --policy.type=<your_policy> \
  --parallelism.dp_shard=4 \
  --accelerator.mixed_precision=bf16 \
  --output_dir=outputs/train/my_policy_fsdp

--parallelism.dp_shard=-1 faz o particionamento entre o número de processos iniciado pelo launcher.

--accelerator.mixed_precision suporta tanto bf16 quanto fp16. Detalhes em precisão mista

Unidades de envolvimento

O FSDP divide o modelo em unidades (tipicamente o bloco de transformer repetido) e reúne uma unidade de cada vez durante o forward/backward. As políticas declaram suas unidades de wrap via _fsdp_wrap_modules na classe da política. Por exemplo, o ACT declara ["ACTEncoderLayer", "ACTDecoderLayer"] e o FastWAM declara ["MoTLayer"]. Para uma política sem uma declaração de _fsdp_wrap_modules, passe um dos flags abaixo. Você pode especificar o nome da classe do módulo explicitamente, ou usar uma política baseada em tamanho:

--accelerator.fsdp.wrap_modules='["MyTransformerBlock"]'   # explicit class names
--accelerator.fsdp.min_num_params=1000000                  # or: wrap every submodule above 1M params

O FSDP não consegue dividir pesos vinculados (por exemplo, uma cabeça de linguagem vinculada ao embedding de entrada) entre unidades de wrap. O torch 2.12 e versões mais novas param no primeiro passo de treinamento e nomeiam o parâmetro, enquanto versões mais antigas os desvinculam silenciosamente. Envolver a classe do bloco repetido geralmente os mantém juntos na unidade raiz.

Se uma política não declarar _fsdp_wrap_modules e nenhum --accelerator.fsdp.wrap_modules ou --accelerator.fsdp.min_num_params for passado, a execução falha na inicialização em vez de envolver silenciosamente apenas o módulo raiz (o que resultaria na perda de todas as economias de memória de sharding).

Outras configurações de sharding:

  • --accelerator.fsdp.reshard_after_forward: se os parâmetros de cada unidade devem permanecer residentes após o forward.
  • --accelerator.fsdp.cpu_offload: mantém parâmetros, gradientes e estados do otimizador na CPU.
  • --accelerator.fsdp.ignored_modules: uma expressão regular de caminhos de módulos para manter não fragmentados.
  • --accelerator.fsdp.mixed_precision_policy.{param_dtype,reduce_dtype,output_dtype,cast_forward_inputs}: os campos do MixedPrecisionPolicy do PyTorch, aplicados a cada unidade FSDP. Assim que qualquer campo for definido, a política é construída apenas a partir desses campos e substitui a derivada de --accelerator.mixed_precision, portanto, defina também param_dtype. Antes do torch 2.15, um reduce_dtype não definido segue o param_dtype. A partir do torch 2.15, ele segue o dtype próprio dos parâmetros (float32 sob precisão mista). float16 requer --accelerator.mixed_precision=fp16, que constrói o loss scaler.

HSDP

Paralelismo de Dados Híbrido Fragmentado: os parâmetros, gradientes e estados do otimizador são fragmentados entre dp_shard ranks, e essa fragmentação é replicada dp_replicate vezes. As operações all-gather de parâmetros e reduce-scatter de gradientes permanecem dentro de um grupo de fragmentos; apenas o all-reduce que sincroniza as réplicas cruza entre os grupos. Os dois graus devem multiplicar para o tamanho do mundo:

# 16 GPUs = 2 nodes × 8: shard within each node, replicate across nodes
torchrun --nnodes=2 --nproc-per-node=8 ... $(which lerobot-train) \
  --parallelism.dp_replicate=2 --parallelism.dp_shard=8 ...

PEFT

Fine-tuning com PEFT (--peft.*) funciona com FSDP2 e HSDP. O modelo base congelado é particionado junto com os adaptadores, de modo que cada rank mantém apenas sua parte dos pesos base:

torchrun --nproc-per-node=4 $(which lerobot-train) \
  --policy.path=${HF_USER}/my_base_policy \
  --peft.method_type=LORA --peft.r=16 \
  --parallelism.dp_shard=4 \
  --accelerator.mixed_precision=bf16 \
  --output_dir=outputs/train/my_policy_fsdp_lora
  • As unidades de encapsulamento ainda vêm da declaração _fsdp_wrap_modules da política (ou --accelerator.fsdp.wrap_modules).
  • Use precisão mista quando o modelo base estiver armazenado em bf16 ou fp16. O PEFT mantém seus adaptadores em fp32, enquanto as cópias de --peft.full_training_modules mantêm o dtype do modelo base, e o FSDP2 precisa de um único dtype para os parâmetros treináveis que ele fragmenta juntos. Com a precisão mista ativada, o accelerate faz o upcast de todos os parâmetros treináveis para fp32.
  • Os checkpoints armazenam o adaptador em vez dos pesos completos, em cada --checkpoint_format (veja Checkpoints).
  • --accelerator.fsdp.ignored_modules é comparado com os nomes dos módulos do modelo PEFT, que começam com base_model.model.. Inicie o padrão com .* para correspondê-los.

Checkpoints

Cada checkpoint contém um diretório pretrained_model/ e um diretório training_state/:

005000/  # the training step at that checkpoint
├── pretrained_model/
│   ├── config.json  # policy config
│   ├── train_config.json  # the full training config
│   ├── model.safetensors  # full weights (checkpoint_format ∈ {safetensors, safetensors_dcp}, or any non-sharded run)
│   ├── pytorch_model_fsdp_0/  # DCP weight shards (checkpoint_format ∈ {dcp, safetensors_dcp})
│   ├── policy_preprocessor.json  # preprocessor config (when the run has a preprocessor)
│   ├── policy_preprocessor_step_*.safetensors  # state of the stateful preprocessor steps
│   ├── policy_postprocessor.json  # postprocessor config (when the run has a postprocessor)
│   └── policy_postprocessor_step_*.safetensors  # state of the stateful postprocessor steps
└── training_state/
    ├── optimizer_param_groups.json  # optimizer param groups (non-sharded runs)
    ├── optimizer_state.safetensors  # optimizer state (non-sharded runs)
    ├── optimizer_0/  # DCP optimizer shards (sharded runs)
    ├── rng_state.safetensors  # rng states
    ├── scheduler_state.json  # scheduler state (when the run has a scheduler)
    ├── scaler_state.json  # fp16 loss-scaler state (mixed_precision=fp16 only)
    └── training_step.json  # step + dp_world_size/batch_size/grad_accum/precision + topology

Durante o treinamento em GPU única ou DDP, o pipeline serializa cada state dict em um único arquivo: model.safetensors para o modelo e optimizer_state.safetensors para o otimizador.

Durante o treinamento particionado, o estado do otimizador é salvo como shards DCP sob training_state/optimizer_0/, e o layout do modelo sob pretrained_model/ pode ser configurado por meio de --checkpoint_format:

--checkpoint_formatArtefato de pesosUse quando
safetensors (padrão)apenas um único model.safetensorsvocê deseja que cada checkpoint seja imediatamente carregável com from_pretrained
dcpapenas o diretório de shard pytorch_model_fsdp_0/reunir todos os pesos torna os salvamentos e retomas muito lentos
safetensors_dcpambosvocê deseja retomar rapidamente e carregar imediatamente checkpoints

Uma execução de PEFT armazena seu adaptador em vez dos pesos completos: adapter_model.safetensors e adapter_config.json substituem model.safetensors, e os shards do DCP contêm apenas o adaptador. O modelo base é carregado a partir do caminho registrado em adapter_config.json.

Duas coisas a saber sobre checkpoints agregados (safetensors) de execuções fragmentadas:

  • Eles armazenam pesos em fp32. No treinamento com precisão mista, o FSDP mantém uma cópia mestre em fp32, e o checkpoint salva a cópia mestre para garantir que o treinamento retome de forma consistente.
  • O gather é coletivo (todos os ranks participam), mas apenas o processo principal grava.

Convertendo checkpoints DCP

lerobot-convert-dcp mescla um diretório de shard DCP em um model.safetensors regular, offline e sem GPUs:

lerobot-convert-dcp --checkpoint_dir=outputs/train/run/checkpoints/005000
lerobot-convert-dcp --checkpoint_dir=... --delete_dcp=true --push_to_hub=${HF_USER}/my_policy

--push_to_hub publica o diretório convertido como um repositório de modelo. Os shards de uma execução PEFT são mesclados em adapter_model.safetensors. Como qualquer checkpoint dcp, um checkpoint PEFT salvo com --checkpoint_format=dcp é carregado com --policy.path somente após essa conversão.

Retomando

Retome com --resume=true --config_path=.../checkpoints/last/pretrained_model/train_config.json. Retomar de um checkpoint DCP suporta o resharing do modelo e do estado do otimizador para a topologia atual, o que significa que você pode retomar com uma divisão diferente de dp_replicate/dp_shard. O data sampler sempre pode retomar na época e no deslocamento corretos, mas é exato por amostra apenas quando o tamanho do mundo e o tamanho do lote correspondem à execução original (um aviso é registrado caso contrário).

Os checkpoints de FSDP gravados pelo LeRobot 0.6.x e versões anteriores utilizavam um layout diferente no disco (um estado completo do otimizador agregado) e não podem ser retomados.

Observações

  • Os salvamentos de checkpoint e as publicações no final do treinamento são coletivos (todos os ranks os executam). Os pesos agregados, os arquivos auxiliares e os uploads para o Hub são gravados apenas pelo processo principal.
  • As métricas são reduzidas entre os ranks antes do registro: as perdas são médias e samples/s relata a taxa de transferência em todo o cluster.
  • O agendamento da taxa de aprendizado é avançado uma vez por etapa de treinamento, independentemente do número de processos (step_scheduler_with_optimizer=False está embutido).

Para mais informações sobre a mecânica subjacente, consulte o guia de FSDP do Accelerate. Para aprofundar-se no treinamento em larga escala, confira o Ultrascale Playbook.

Update on GitHub