mirror of
https://github.com/huggingface/lerobot.git
synced 2026-07-19 16:02:11 +00:00
1050c2fb6c
Replace the shard/Backtrackable/decoded-shuffle-buffer internals with an
episode pool: each (rank x worker) consumer keeps episode_pool_size whole
episodes' tabular rows in RAM and emits uniformly random frames across
them. delta_timestamps windows become exact in-RAM slices with correct
boundary padding (the Backtrackable machinery and its lookback/lookahead
ceilings are gone), and video is decoded only when a sample is emitted,
so pool memory stays tabular-sized instead of buffer_size decoded
samples.
- Prefetch-on-admit: when streaming from a remote source, each pooled
episode's video files download to a local cache in the background
(refcounted, since v3 packs several episodes per file; deleted on
eviction), so decode-on-exit reads local bytes instead of paying
network seek latency.
- Per-consumer RNG derived from (seed, epoch, rank, worker): consumers
decorrelated, runs reproducible, epochs reshuffle automatically.
- Deterministic fast-forward resume: load_state_dict takes the trainer's
{batches_consumed, batch_size}; each worker re-derives its own skip
from the DataLoader's round-robin batch assignment and replays
tabular-only (no decode). Exact within an epoch, works with
num_workers > 0, and the same state file serves every rank. Replaces
the per-shard HF state_dict approach, which lived in worker processes
and could not be captured from the trainer.
- Shard-cap default removed (max_num_shards=None uses every parquet
shard); runtime warnings for non-divisible world sizes (datasets
degrades to read-everything splitting) and workers left without
shards.
- episode_pool_size replaces buffer_size (deprecated, ignored with a
warning); decoder cache sized to the pool working set, capped at 128.
Legacy order-replication tests asserted the old buffer algorithm
step-by-step and are rewritten as behavior contracts (exactly-once
coverage, per-seed determinism, epoch reshuffle). Value-level parity
tests against the map-style dataset pass unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
50 lines
1.7 KiB
Bash
50 lines
1.7 KiB
Bash
#!/bin/bash
|
|
#SBATCH --job-name=stream_robocasa
|
|
#SBATCH --nodes=2
|
|
#SBATCH --ntasks-per-node=1
|
|
#SBATCH --gpus-per-node=8
|
|
#SBATCH --cpus-per-task=96
|
|
#SBATCH --exclusive
|
|
#SBATCH --time=24:00:00
|
|
#SBATCH --output=logs/%x-%j.out
|
|
|
|
# Multinode streaming training over a large HF-hosted RoboCasa dataset (never touches local disk).
|
|
# Launches examples/scaling/train_streaming_multinode.py with Accelerate. Each rank streams a disjoint
|
|
# set of shards via split_dataset_by_node (auto-resolved from the Accelerate state), so per-node
|
|
# throughput scales independently. For an even split, ensure n_shards % (nodes * gpus_per_node) == 0.
|
|
#
|
|
# Submit with: sbatch slurm/train_streaming_robocasa.sh
|
|
|
|
set -euo pipefail
|
|
|
|
REPO_ID=${REPO_ID:-pepijn223/robocasa_pretrain_human300_v4}
|
|
GPUS_PER_NODE=8
|
|
NUM_PROCESSES=$((SLURM_NNODES * GPUS_PER_NODE))
|
|
|
|
# Rendezvous: use the first node in the allocation as the main process.
|
|
MAIN_ADDR=$(scontrol show hostnames "$SLURM_JOB_NODELIST" | head -n1)
|
|
MAIN_PORT=${MAIN_PORT:-29500}
|
|
|
|
export HF_HOME=${HF_HOME:-$SCRATCH/hf_home}
|
|
# Avoid each rank fighting over the tokenizers' internal thread pool.
|
|
export TOKENIZERS_PARALLELISM=false
|
|
|
|
srun --kill-on-bad-exit=1 bash -c '
|
|
accelerate launch \
|
|
--num_machines '"$SLURM_NNODES"' \
|
|
--num_processes '"$NUM_PROCESSES"' \
|
|
--machine_rank $SLURM_NODEID \
|
|
--main_process_ip '"$MAIN_ADDR"' \
|
|
--main_process_port '"$MAIN_PORT"' \
|
|
--mixed_precision bf16 \
|
|
--dynamo_backend no \
|
|
examples/scaling/train_streaming_multinode.py \
|
|
--repo_id '"$REPO_ID"' \
|
|
--batch_size 64 \
|
|
--num_workers 12 \
|
|
--episode_pool_size 64 \
|
|
--steps 200000 \
|
|
--save_freq 2000 \
|
|
--log_freq 50
|
|
'
|