LeRobot documentation

멀티-GPU 학습

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

멀티-GPU 학습

LeRobot는 Hugging Face Accelerate를 통해 여러 GPU에서 학습합니다. 세 가지 데이터 병렬 레이아웃을 지원합니다:

레이아웃기능설정
DDP모든 GPU에 전체 모델을 복제합니다멀티-GPU 실행 시 기본적으로
FSDPShards 파라미터, 그래디언트 및 옵티마이저 상태를 GPU에 걸쳐 분산--parallelism.dp_shard=N
HSDPGPU 그룹 내에서 샤드를 분할하고, 그룹 간에 복제합니다--parallelism.dp_replicate=R --parallelism.dp_shard=S

설치

accelerate는 training extra에 포함되어 있습니다:

pip install 'lerobot[training]'

발행

분산 학습은 torchrun과 accelerate launch를 통해 모두 시작할 수 있습니다. Accelerate는 단순한 런처로 사용되며, 학습 구성을 관리하지 않습니다. 모든 분산 학습 설정은 LeRobot 자체의 구성 시스템에 포함되어 있습니다.

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

accelerate launch(일반 런처로):

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

--parallelism.* 플래그가 없는 경우, 멀티 프로세스 실행은 일반 DDP를 실행합니다. 멀티 노드 실행에는 표준 torchrun --nnodes/--node-rank/--rdzv-endpoint 플래그(또는 accelerate launch --num_machines/--machine_rank/--main_process_ip)를 사용합니다.

Accelerate의 YAML 설정 파일(accelerate launch --config_file some.yaml, accelerate config)은 지원되지 않습니다. 이러한 파일은 환경 변수를 통해 엔진을 구성하여 LeRobot의 설정 시스템을 우회하므로, train_config.json이 실제 실행에 사용된 설정을 더 이상 설명하지 못하게 됩니다. 따라서 accelerate 환경 변수가 설정된 경우 lerobot-train은 시작을 거부합니다. 대신 --parallelism.* / --accelerator.* 플래그에 설정을 지정하거나, LEROBOT_ALLOW_ACCELERATE_ENV=1을 설정하여 오버라이드를 확인하고 계속 진행할 수 있습니다.

배치 의미론, 학습률, 스텝

각 dp_replicate × dp_shard 데이터 병렬 워커는 단계마다 자체 --batch_size 마이크로 배치씩을 로드하므로, 하나의 학습 단계는 batch_size × dp_world_size개의 샘플을 소비하며, 이 중 × gradient_accumulation_steps만큼이 각 옵티마이저 업데이트에 반영됩니다:

effective_batch_size = batch_size × dp_world_size × gradient_accumulation_steps

학습 배너는 시작 시 이 분해를 출력합니다. --steps는 옵티마이저 업데이트가 아닌 루프 단계(워커당 마이크로 배치)를 세웁니다.

Gradient accumulation은 1급 플래그입니다:

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

LeRobot는 유효 배치 크기가 증가할 때 학습률이나 스텝 수를 자동으로 스케일링하지 않습니다. 스케일아웃하여 동등한 학습을 원할 경우, 예를 들어 GPU 2개를 사용할 때 --optimizer.lr을 두 배로 늘리거나(선형 스케일링) --steps를 절반으로 줄이는 방식으로 수동으로 조정해 주세요.

Sharded training (FSDP)

모델이 DDP로 학습하기에 너무 크다면 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은 런처가 시작한 프로세스 수만큼 샤딩합니다.

--accelerator.mixed_precision는 bf16와 fp16를 모두 지원합니다. 자세한 내용은 혼합 정밀도를 참고하세요.

Wrap units

FSDP는 모델이 반복되는 transformer 블록과 같은 단위별로 모델을 분할(shard)하고, forward/backward 과정에서 한 번에 하나의 단위를 수집(gather)합니다. 정책(policy) 클래스의 _fsdp_wrap_modules를 통해 wrap 단위를 선언합니다. 예를 들어, ACT는 ["ACTEncoderLayer", "ACTDecoderLayer"]를, FastWAM은 ["MoTLayer"]를 선언합니다. _fsdp_wrap_modules 선언이 없는 정책의 경우, 아래 플래그 중 하나를 전달하십시오. 모듈 클래스 이름을 명시적으로 지정하거나, 대신 크기 기반 정책을 사용할 수 있습니다:

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

FSDP는 묶인 가중치(예: 입력 임베딩에 묶인 언어 헤드)를 랩핑 단위 간에 분할할 수 없습니다. torch 2.12 이상에서는 첫 번째 학습 단계에서 중단되고 해당 파라미터 이름을 명시하는 반면, 이전 버전에서는 이를 조용히 분리합니다. 반복되는 블록 클래스를 랩핑하면 일반적으로 이러한 가중치가 루트 단위에 함께 유지됩니다.

정책이 _fsdp_wrap_modules를 선언하지 않고 --accelerator.fsdp.wrap_modules 또는 --accelerator.fsdp.min_num_params도 전달되지 않으면, 실행은 시작 시점에 실패합니다. 루트 모듈만 조용히 래핑하는 것(모든 샤딩 메모리 절감 효과를 포기하게 됨)을 방지하기 위함입니다.

다른 샤딩 설정:

  • --accelerator.fsdp.reshard_after_forward: forward 이후 각 유닛의 파라미터를 유지할지 여부.
  • --accelerator.fsdp.cpu_offload: 매개변수, 기울기 및 옵티마이저 상태를 CPU에 유지합니다.
  • --accelerator.fsdp.ignored_modules: 샤딩하지 않고 유지할 모듈 경로에 대한 정규식입니다.
  • --accelerator.fsdp.mixed_precision_policy.{param_dtype,reduce_dtype,output_dtype,cast_forward_inputs}: PyTorch의 MixedPrecisionPolicy 필드로, 모든 FSDP 유닛에 적용됩니다. 어떤 필드라도 설정되면, 해당 필드만으로 정책이 구성되며 --accelerator.mixed_precision에서 파생된 정책을 대체하므로 param_dtype도 함께 설정해야 합니다. torch 2.15 이전에는 reduce_dtype가 설정되지 않으면 param_dtype를 따릅니다. torch 2.15부터는 매개변수 자체의 dtype(float32 mixed precision 환경)을 따릅니다. float16은 loss scaler를 구성하는 --accelerator.mixed_precision=fp16이 필요합니다.

HSDP

Hybrid Sharded Data Parallel: 파라미터, 그래디언트 및 옵티마이저 상태는 dp_shard 랭크에 걸쳐 샤딩되며, 이 샤딩은 dp_replicate 번 복제됩니다. 파라미터 올게더(all-gather)와 그래디언트 리듀스스캐터(reduce-scatter)는 샤드 그룹 내에서만 수행되며, 레플리카를 동기화하는 올리듀스(all-reduce)만 그룹 간을 오갑니다. 두 차원의 곱이 월드 사이즈(world size)와 같아야 합니다:

# 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

PEFT fine-tuning(--peft.*)는 FSDP2와 HSDP에서 작동합니다. 동결된 base model은 adapter와 함께 sharding되며, 각 rank는 base weights의 자기 shard만 보유합니다:

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
  • Wrap unit은 여전히 정책의 _fsdp_wrap_modules 선언(또는 --accelerator.fsdp.wrap_modules)에서 가져옵니다.
  • 기본 모델이 bf16 또는 fp16로 저장된 경우 혼합 정밀도를 사용하세요. PEFT는 어댑터를 fp32로 유지하는 반면, --peft.full_training_modules의 복사본은 기본 모델의 dtype을 유지합니다. FSDP2는 함께 샤딩하는 학습 가능 매개변수에 대해 단일 dtype이 필요합니다. 혼합 정밀도를 켜면 accelerate는 모든 학습 가능 매개변수를 fp32로 업캐스트합니다.
  • --checkpoint_format의 모든 경우에서 체크포인트는 전체 가중치가 아닌 어댑터를 저장합니다(Checkpoints 참고).
  • --accelerator.fsdp.ignored_modules는 PEFT 모델의 모듈 이름과 일치하며, 이 이름은 base_model.model.로 시작합니다. 일치하려면 패턴을 .*로 시작하세요.

체크포인트

모든 체크포인트에는 pretrained_model/ 디렉터리와 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

단일 GPU 또는 DDP 학습 중에 파이프라인은 각 상태 딕셔너리를 단일 파일로 직렬화합니다: 모델은 model.safetensors, 옵티마이저는 optimizer_state.safetensors입니다.

sharded 학습 중에는 옵티마이저 상태가 training_state/optimizer_0/ 아래에 DCP 샤드로 저장되며, pretrained_model/ 아래 모델 레이아웃은 --checkpoint_format를 통해 구성할 수 있습니다:

--checkpoint_formatWeights 아티팩트사용 시
safetensors (기본값)model.safetensors 단일 파일만모든 체크포인트를 from_pretrained로 즉시 로드할 수 있기를 원합니다
dcppytorch_model_fsdp_0/ 샤드 디렉터리만전체 가중치를 수집하는 것은 저장 및 재개를 너무 느리게 만듭니다
safetensors_dcp둘 다빠른 재개 및 즉시 로드 가능한 체크포인트를 원합니다

PEFT 실행은 전체 가중치가 아닌 어댑터를 저장합니다: adapter_model.safetensors와 adapter_config.json이 model.safetensors를 대체하며, DCP 샤드는 어댑터만 포함합니다. 베이스 모델은 adapter_config.json에 기록된 경로에서 로드됩니다.

분할 실행에서 생성된 수집된 (safetensors) 체크포인트에 대해 알아야 할 두 가지 사항:

  • fp32 가중치를 저장합니다. 혼합 정밀도 학습에서 FSDP는 fp32 마스터 복사본을 유지하며, 체크포인트는 훈련이 일관되게 재개되도록 마스터 복사본을 저장합니다.
  • gather는 집합 연산(모든 rank가 참여)이지만, 메인 프로세스만 데이터를 기록합니다.

DCP 체크포인트 변환

lerobot-convert-dcp는 DCP 샤드 디렉터리를 GPU 없이 오프라인에서 일반적인 model.safetensors 파일로 병합합니다:

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는 변환된 디렉터리를 모델 저장소로 게시합니다. PEFT 실행의 샤드는 adapter_model.safetensors로 병합됩니다. 모든 dcp 체크포인트와 마찬가지로, --checkpoint_format=dcp로 저장된 PEFT 체크포인트는 이 변환 후에만 --policy.path로 로드됩니다.

재개

--resume=true --config_path=.../checkpoints/last/pretrained_model/train_config.json을 사용하여 재개합니다. DCP 체크포인트에서 재개하는 경우 모델과 옵티마이저 상태를 현재 토폴로지에 맞게 리샤딩하는 것을 지원하므로, 다른 dp_replicate/dp_shard 분할로 재개할 수 있습니다. 데이터 샘플러는 항상 올바른 에포크와 오프셋에서 재개할 수 있지만, 월드 사이즈와 배치 사이즈가 원래 실행과 일치할 때만 샘플 단위 정확도를 보장합니다(일치하지 않으면 경고가 기록됩니다).

LeRobot 0.6.x 및 이전 버전에서 작성한 FSDP 체크포인트는 다른 디스크 레이아웃(집합된 전체 옵티마이저 상태)을 사용하므로 재개할 수 없습니다.

The input is a single word "Notes". 참고

  • Checkpoint 저장과 학습 종료 시 게시는 집합 연산(모든 랭크가 진입)입니다. 수집된 가중치, 사이드카 파일 및 Hub 업로드는 메인 프로세스에서만 작성됩니다.
  • 로그 기록을 위해 메트릭은 랭크 간에 축소됩니다. 손실은 평균화되고, samples/s는 클러스터 전체의 처리량을 보고합니다.
  • 학습률 스케줄링은 프로세스 수와 관계없이 학습 단계마다 한 번씩 진행됩니다(step_scheduler_with_optimizer=False가 기본으로 적용됨).

기본 메커니즘에 대한 배경 지식을 보려면 Accelerate FSDP 가이드를 참고하세요. 대규모 학습에 대해 더 깊이 알고 싶다면 Ultrascale Playbook를 확인해 보세요.

Update on GitHub