Repository navigation
feat(fsdp): ref model refactor, frozen ref/teacher models, EMA optimizer, pinned offload - #263
Merged
Merged
Conversation
3 of 6 tasks
Rockdu
force-pushed
the
feat/fsdp-ref-models
branch
2 times, most recently
from
September 27, 2026 00:26
855f711 to
065c661
Compare
Rockdu
force-pushed
the
feat/fsdp-ref-models
branch
from
September 27, 2026 00:45
065c661 to
14615bf
Compare
This was referenced Sep 27, 2026
Merged
OnePunchMonk
pushed a commit
to OnePunchMonk/miles_diffusion
that referenced
this pull request
Oct 5, 2026
OnePunchMonk
pushed a commit
to OnePunchMonk/miles_diffusion
that referenced
this pull request
Oct 5, 2026
…zer, pinned offload (radixark#263) * refactor(fsdp): [mechanical] extract actor model loading * feat(fsdp): parameterize model loading for frozen roles * feat(fsdp): offload model and optimizer tensors to pinned CPU memory * feat(fsdp): load pretrained actor LoRA adapters and publish their metadata * fix(fsdp): isolate base-reference inference from actor training state * feat(fsdp): load independent frozen reference and teacher models * feat(fsdp): store EMA in a checkpointed optimizer * fix(fsdp): update EMA once after training instead of on every weight publication * docs(fsdp): explain model roles and offload lifecycles
4 of 6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
--ref-mode ref --ref-load <ckpt>and--teacher-load <ckpt>load their own frozen FSDP models through the actor's loader (same components, mesh and input prep), each optionally with a pretrained PEFT adapter (--ref-lora-adapter-path,--teacher-lora-adapter-path) and native FSDP CPU offload (--ref-cpu-offload,--teacher-cpu-offload). Teacher models are exposed to custom losses asctx.teacher_models; no loss consumes them yet.torch.optim.Optimizer.EMAOptimizerkeepsstate[param]["ema"]next to its parameter, is saved/loaded through DCP underema/(independent of--no-save-optim), cold-starts from the loaded weights on older checkpoints, and updates once after each rollout's training instead of on every weight publication.use_weights()swaps EMA values into the actor's shards in place (no full copy of the trainable weights).--offload-trainsleep/wake now moves the actor, reference, teacher, AdamW and EMA state between GPU and pinned host memory, preserving Parameter objects, optimizer bindings, FSDP shard views/padding and shared buffers.--lora-adapter-pathresumes training from a saved PEFT adapter;--lora-rank/--lora-alphamust match it, and LoRA IPC weight sync reads rank/alpha from the loaded adapter config.--ref-mode lora_baseis kept (adapter disabled on the actor, no second base model).Why
Three non-obvious traps handled here:
reshard_after_forward=False,disable_adapter()re-enables adapterrequires_gradon exit while the gathered parameters are registered, leaving the shards frozen; the next training step then has no LoRA gradients. The lora_base forward reshards before leaving the context (regression test:test_lora_base_reference_keeps_adapter_gradients_on_fsdp_shards).attempting to assign a gradient with dtype 'c10::Half' to a tensor with grad_dtype 'Float', seen intest_sd3_ocr_grpo_2xGPU).load_fsdp_modelsnow finishes the lazy init at load time, while the trainable set is final, so the order of reference/teacher/actor forwards no longer matters (regression test:test_first_forward_with_adapters_disabled_keeps_master_dtype_gradients). The forward order itself is kept as onmain(actor first).use_weights()reshards before swapping in and before swapping back.Validation
Pinned vs pageable phase offload — Qwen-Image Flow-GRPO recipe (
run_diffusion_grpo_pickscore_5gpu_flowgrpo_aligned.py), 5×H200, LoRA, colocate,--deterministic-mode, steady-state rollouts 1–3 (measured on an earlier revision of this branch's offload code):Current offload implementation — standalone 4-rank FSDP2 Qwen-Image + recipe LoRA (3373 tensors, 20.9 GB/rank), steady state: offload 0.58 s → 0.40 s, onload 0.57 s → 0.40 s vs the previous revision. Raw pinned D2H is 42–50 GB/s per rank with 4 ranks copying concurrently, so the copies are near hardware speed.
Known cost not addressed here: under
torch.use_deterministic_algorithms(True)(i.e.--deterministic-mode), PyTorch NaN-fills every new pinned buffer (torch.utils.deterministic.fill_uninitialized_memory), which adds ~2.3 s to each sleep on this recipe. Without deterministic mode the offload is ~0.6 s.E2E standard change:
test_sd3_nft_pickscore_3xGPU(re-recorded infix(fsdp): update EMA once after training ...)The SD3 NFT e2e (
--ref-mode ema --use-ema --ema-rollout-policy ema,--ema-decay-flat-steps 0, so the decay changes with every EMA update) drifts from step 2 on, in 8 of its 10 series; steps 0–1,raw_num_samplesandnft_t_meanare unchanged. Cause:main, EMA updates insideupdate_weights, which also runs once before training starts, so after rollout k the update count is k+2; it now updates only after training, so the count is k+1 and every decay is one step earlier.torch._foreach_lerp_instead ofmul_(d).add_(x, alpha=1-d)(same math, different rounding).Step 1's fp16 grad-scaler overflow leaves the weights unchanged, so EMA equals the actor until step 2 whatever the decay; hence the drift starts there.
Attribution, recorded with
record-e2e-standards.ymlon the verifying["h200", "3gpu"]runner class: this branch plus a throwaway commit restoringmain's update cadence and formula reproduces the committedmainstandard bit for bit, on both the pre-#257 and the currentmainbase. This branch's head reproduces the values the PR CI reported (e.g.rollout/reward/raw_mean[2] = 0.7545289993286133); that recording is the new standard. No other standard changes.Correctness
requires_grad, DTensor spec, Parameter identity, channels_last / non-contiguous buffers and shared-buffer aliasing; everything is pinned after offload.tests/fast-gpu/backends/fsdp_utils/test_offload.pyandtest_reference_models.pypassed on the offload revision; not re-run after the last two changes (lora_base /use_weightsrewrite, rollout-default revert).test_offload,test_ema_optimizer,test_reference_models,test_reference_arguments,test_loss_hub_nft,test_sglang_parallel_defaults).tests/fast-gpu/.../test_reference_models.pyneedsPYTHONPATH=<repo>for its worker to importtests.*; that also fails the same way without this PR.Files
miles/backends/fsdp_utils/model_loader.py— new: shared FSDP model loader (mechanical extraction fromactor.py, then frozen roles + adapters).miles/backends/fsdp_utils/offload.py— new: pinned-memory model/optimizer phase offload.miles/backends/fsdp_utils/ema.py—EMAOptimizer,use_weights,reshard_model.miles/backends/fsdp_utils/actor.py— load ref/teacher, EMA wiring, sleep/wake, reference forwards.miles/backends/fsdp_utils/checkpoint.py— save/load EMA underema/.miles/backends/fsdp_utils/model_backend.py,models/ltx/loading.py,models/package.py—load_componenttakes an explicitcheckpoint_path.miles/backends/fsdp_utils/diffusion_update_weight_utils.py— IPC LoRA metadata from the loaded adapter.miles/backends/fsdp_utils/loss_hub/types.py,loss_hub/flow_grpo.py— expose reference/teacher models; KL error message.miles/utils/arguments.py— new flags and validation.docs/fsdp_model_roles.md— model roles and offload lifecycles.tests/fast/...,tests/fast-gpu/...— CPU and 2-GPU coverage for the above.Commits
refactor(fsdp): [mechanical] extract actor model loading— pure move, reviewable separately.feat(fsdp): parameterize model loading for frozen rolesfeat(fsdp): offload model and optimizer tensors to pinned CPU memoryfeat(fsdp): load pretrained actor LoRA adapters and publish their metadatafix(fsdp): isolate base-reference inference from actor training statefeat(fsdp): load independent frozen reference and teacher modelsfeat(fsdp): store EMA in a checkpointed optimizerfix(fsdp): update EMA once after training instead of on every weight publication— also re-records the SD3 NFT e2e standard (see above)docs(fsdp): explain model roles and offload lifecyclesNot in this PR: renaming
--ema-rollout-policyto--rollout-weights(stacked follow-up PR).Checklist
pre-commit run --all-filespasses — only run on this branch's changed files (--from-ref origin/main), which passpytest -xis green — only the focused CPU suites listed above were run (local env has no sglang); 2-GPU suites not re-run after the last two changespython3 train.py --helpstill parses — not run--ref-load,--teacher-load,--ref-lora-adapter-path,--teacher-lora-adapter-path,--ref-cpu-offload,--teacher-cpu-offload,--lora-adapter-pathand--ref-mode refare missing fromdocs/user-guide/cli-reference.md