Allow policies to declare their input image format - #46
acwrenn-nv wants to merge 9 commits into
Conversation
a4db164 to
bf30f63
Compare
03d7836 to
f971773
Compare
|
Ran an independent A/B verification of this PR on real hardware (RTX PRO 6000, torch 2.11 cu128) with a real 52k-frame SO-101 dataset (2 cams, 480×640), the N1.7 3B checkpoint, 1. Numeric parity: byte-exact ✅Same fixed batch, same seeds, through both branches ( Also worth noting: the old 2. End-to-end training step (30 steps, medians, n=30)
Effect is ~7σ vs step-to-step noise (σ ≈ 11–16 ms). The 3. Where the remaining GPU headroom is (nsight systems, NVTX GPU-projected)During the preprocessor range the GPU is 1.2% busy — it's a pure CPU-serial bubble. Inside
GPU-bound floor (fwd+bwd+optim) is 408 ms → 78.4 samples/s ideal. PR46 lands at 56.5, so ~+39% is still on the table, all of it in that CPU bubble. Suggested follow-up (separate PR)Rather than accelerating the transforms (which risks the bit-exact albumentations contract), overlap them: prefetch one batch ahead through pack+VLM-encode in a background thread (or push it into the dataloader workers) with a double buffer. Then Verdict: LGTM. Clean opt-in contract, backward compatible (legacy configs default to float, old serialized GR00T pipelines get upgraded at load), byte-exact, +17% measured end-to-end. Method note: the gated |
|
Follow-up: gradient-level verification (was asked whether the parity claim covers gradient calculation — it does now). Gradient parity: main vs PR46 on the real 3BFull forward+backward on a fixed real-data batch, per-tensor SHA256 over all 537 gradient tensors, TF32 disabled, same seeds. Crucially, with a run-vs-run determinism control (same code executed twice) to calibrate what "different" even means here.
The control matters: the 3B backward is inherently nondeterministic run-to-run (the same ~500 tensors — DiT action head blocks — change hashes between two identical runs; classic atomics nondeterminism). So raw hashes can't be the criterion. The criterion is whether main↔PR46 differs more than run↔run:
Median ratio = 1.20 → main-vs-PR46 sits inside the same noise envelope as re-running identical code. Combined with the byte-exact preprocessor outputs and bit-identical loss (forward is deterministic; only backward has atomics), the conclusion is: no gradient difference attributable to this PR. AdamW
|
Title
Allow policies to declare their input image format
Summary / Motivation
GR00T N1.7 dataset workers already produce compact
uint8images, but the training loop converted them to float32[0, 1]before the GR00T preprocessor converted them back touint8and staged them through a CPU NumPy/HWC buffer. This change adds an explicit class-level raw-image input contract to policies so GR00T can preserve worker-produceduint8tensors through packing and transfer. Existing policies inherit the historical float32 behavior without adding policy-specific state to serialized processor configs.The GR00T
videointermediate is now an ordered tuple of per-camera(B, T, C, H, W)tensors. The cv2/Albumentations path still converts individual frames to HWC at its point of use, preserving the reference transform and crop behavior while removing the full-batch staging copy.Related issues
What changed
ImageInputFormatcontract toPreTrainedPolicy, withfloat32_0_1as the inherited default and no processor-pipeline serialization.uint8images only when the selected policy expects float32 input; the value is captured before PEFT or Accelerate wraps the model.GrootPolicy.input_image_format = UINT8_0_255and removed image-format state from new and loaded GR00T preprocessors.How was this tested (or how to run locally)
Targeted touched-file suite:
CUDA run on the current PR head: 169 passed, 7 skipped.
Independent real-hardware A/B on an RTX PRO 6000 with a 52k-frame, two-camera SO-101 dataset, the N1.7 3B checkpoint,
use_albumentations=true, and batch size 32:Full benchmark methodology and parity results: A/B verification and gradient follow-up.
W&B training/performance results
These performance results apply to the MR as a whole. The class-level
ImageInputFormatdeclaration changes where the input contract lives without changing image values, preprocessing, or the training execution path.Runs are in
nvidia/lerobot-gr00t-17n-train. After a 10% warmup, examples/s is mediantrain/samples_per_sand GPU utilization is meansystem.gpu.*.gpuacross GPUs with model memory allocated.Four-suite performance comparison (mean across LIBERO-10, Spatial, Object, and Goal; global batch 640, 2×320)
Checklist (required before merge)
pre-commit run -a) — targeted Ruff format/check passes on all changed files; full pre-commit was not run.pytest) — the targeted touched-file suite passes; the full suite was not independently verified.Reviewer notes
ImageInputFormatownership onPreTrainedPolicy, the GR00T class override, capture before model wrappers, and the ordered per-camera tensor contract betweenGrootN17PackInputsStepandGrootN17VLMEncodeStep.