[trainer, worker, fsdp, cfg, tests] feat: add multi-role distillation runtime - #546
Draft
NancyFyong wants to merge 8 commits into
Draft
Conversation
This was referenced Sep 5, 2026
… runtime Bind the generic distillation control plane to colocated FSDP role groups with independent optimizer state, named-LoRA role switching, EMA, profiling metrics, and atomic composite checkpoint/resume. Preserve an independent-module correctness path and fail closed at deferred architecture and adversarial boundaries. Refs: verl-project#519 AI assistance (OpenAI Codex) was used for this change. Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: NancyFyong <2742092809@qq.com>
Match the established worker profiler setup so nested tool settings are converted from OmegaConf before DistProfiler construction. This prevents production distillation workers from failing during actor initialization. AI assistance (OpenAI Codex) was used for this change. Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: NancyFyong <2742092809@qq.com>
Resolve DataProtoFuture values returned by nonblocking worker dispatch before the driver converts phase metrics and optimizer counters. This lets the real Ray data plane complete a distillation cycle. AI assistance (OpenAI Codex) was used for this change. Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: NancyFyong <2742092809@qq.com>
…stabilize resume Resolve phase RPC failures before collecting lazy rank metadata, construct only the actor subconfigs needed by distillation, and fingerprint plans through canonical JSON rather than order-dependent repr strings. Keep newly introduced helpers flat and descriptively named. Inspect fake adapters directly in isolation tests instead of using inference export. Validation: 449 CPU regressions, both one-rank FSDP role/checkpoint tests, generated-config verification, and all pre-commit hooks passed. Refs verl-project#535 AI assistance (OpenAI via pi) was used for this change. Co-authored-by: OpenAI <noreply@openai.com> Signed-off-by: NancyFyong <2742092809@qq.com>
Carry the PR 1 controller naming through checkpoint state handling and tests after rebasing the multi-role runtime. Keep framework-defined private hooks unchanged. AI assistance (OpenAI via pi) was used for this change. Co-authored-by: OpenAI <noreply@openai.com> Signed-off-by: NancyFyong <2742092809@qq.com>
NancyFyong
force-pushed
the
distillation-pr2-runtime
branch
from
September 6, 2026 03:15
80d7b92 to
ddbcd4e
Compare
…utionMatchingComputer The architecture-owned differentiable computation object misused the *Runner suffix, which in this repo denotes a top-level task entrypoint (TaskRunner, RayTrainerTaskRunner). Rename it to match the algorithm family it belongs to and the DistributionMatchingModelAdapter that builds it: DistillationPhaseRunner -> DistributionMatchingComputer (Protocol) build_distillation_phase_runner-> build_distribution_matching_computer (hook) self.phase_runner -> self.dm_computer (worker attr) phase_runner_rank_*.pt -> dm_computer_rank_*.pt (per-rank state) The control-plane phase contracts (PhaseRequest, PhaseResult, UpdatePhaseSpec, DistillationPhaseExecutor) and the compute_phase method are deliberately kept, since a cycle is genuinely modelled as student/fake phases. Renaming the per-rank state file changes resume compatibility for pre-existing checkpoints. Validated in the required environment: 449 focused trainer/worker CPU tests pass; ruff, mypy, generated-config verification and all staged pre-commit hooks pass. Co-authored-by: OpenAI Codex Signed-off-by: NancyFyong <2742092809@qq.com>
…-batches Allow architecture computers to declare an explicit loss denominator. Accumulate numerator gradients and normalize over data-parallel counts before clipping and stepping; preserve sample means by default. Validation: 470 targeted CPU tests passed; applicable pre-commit hooks, config regeneration, and diff checks passed. AI assistance (pi coding agent) was used for this change. Co-authored-by: pi coding agent Signed-off-by: NancyFyong <2742092809@qq.com>
Merge distillation-acceleration without rewriting published history. The resulting tree is identical to the CPU-tested repair snapshot. AI assistance (pi coding agent) was used for this change. Co-authored-by: pi coding agent Signed-off-by: NancyFyong <2742092809@qq.com>
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 does this PR do?
Draft — PR 2 of the distribution-matching architecture, stacked on #545.
Bind PR 1's control-plane executor to the existing Ray/FSDP lifecycle with independently optimized semantic roles, shared-base LoRA or colocated independent storage, student EMA, and composite checkpoint/resume.
Parent design: #519. Concrete data-plane architecture: #535. Base contracts: #520. This slice has no architecture-specific phase computer and does not, by itself, make DMD training runnable. Qwen and other model adapters remain separate follow-ups.
Updated and locally validated head:
1a0edbb99d1ebf0d324ff7033dc0666530a833c6(2026-09-07). Incremental diff against PR 1: 26 files, +3,285 / −63. The base branchdistillation-accelerationis atae2c34c; its fixes were merged without rewriting published history. Merge PR 1 first, then retarget/rebase this PR ontomainas needed; do not merge this slice independently of its contracts.Checklist Before Starting
[{modules}] {type}: {description}.Non-duplication: this is the dependent runtime layer, not a second implementation of PR 1. Existing OPD work (#293, #498, #375, #495) does not provide independent student/fake-score optimizers, shared-base role composition, or the composite checkpoint lifecycle. No OPD objective/scheduler is replaced.
Test
Current-head local verification. The merge result is tree-identical to the tested repair snapshot:
Historical GPU evidence at
80d7b92— not rerun for the current repair:PYTHONPATH=. python -m pytest tests/workers/test_distillation_fsdp_roles.py --no-cov -q # 2 passed: one-rank FSDP1 and FSDP2The GPU tests use a tiny model, real FSDP wrappers, named LoRA, and a small test checkpoint manager. They exercise pending-student-graph preservation across frozen role switches, gradient/optimizer isolation, EMA, role export, and model/optimizer/scheduler round-trip. They are not a full production Ray checkpoint or multi-rank inference test. Architecture-specific multi-rank/real-model evidence belongs to the later adapter PR, not to this slice.
Current CPU verification used Python 3.11 / PyTorch 2.13.0+cu129 with repository-matching verl and vLLM-Omni pins. Applicable pre-commit hooks (including mypy), docs/config checks and generated-config verification passed. The dependent PR 5 stack also passed 1,521 full L1 CPU tests. The new denominator collective is CPU-simulated; no new GPU, real multi-rank FSDP or pinned-runtime inference validation is claimed here. Historical GPU evidence above does not establish those properties. Upstream CI results are separate from these local checks. The current CPU workflow filters PR base branches to
main/v0.*; this stacked base is therefore excluded until retargeting or an explicit maintainer-supported run. Theci-corelabel requests the applicable upstream checks without claiming that every workflow has run.API and Usage Example
Schema fragment for a future registered architecture adapter; not a standalone launch recipe:
The architecture opts in via
DistributionMatchingModelAdapter.build_distribution_matching_computer(model_config, plan). Its returned object must implementcompute_phase(request, batch, runtime),state_dict(), andload_state_dict(state).compute_phasereturns one graph-bearing scalar role loss plus detached numeric metrics and optionalloss_normalizer; the generic runtime owns backward and optimization.Review fix — explicit reduction contract:
loss_normalizer=Nonekeeps sample-mean accumulation unchanged.loss * loss_normalizernumerator gradients, then divides by the engine gradient-DP group's averaged count before clipping/stepping. Wan ODE in PR 5 uses its active-element count, preserving physical-batch equivalence when frame masks differ.zero_gradclears normalization state./lossmetrics use the same local micro-batch denominators; existing rank-level metric reduction and other count/timing policies remain unchanged.Design & Code Changes
Physical storage and logical roles are separate:
DiffusionDistillationWorkerreuses verl's worker/dispatch/profiler APIs andEngineRegistry; the role engine extends the existing Diffusers FSDP engine rather than adding another model-loader/backend stack.dmd2as a PPO loss name. Profiler/tool configs are typed beforeDistProfilerconstruction.use_orig_params=true. Optimizer parameter ownership is disjoint; inactive-role gradients fail closed. Role contexts restore prior adapter and train/eval state.DataProtoFuturebefore extracting results. Architecture computers must still synchronize collective-dependent rollout decisions.studentorstudent_emaand uses that adapter's own PEFT config. This is an export API, not completed CheckpointEngine/validation-replica integration.Detailed ownership, initialization and phase sequence, checkpoint layout, failure/recovery behavior, configuration mapping, and test boundaries are in #535.
Non-goals: a Qwen/Wan implementation, standalone score transport, multi-optimizer adversarial phases, causal attention/KV caches, pipeline parallelism, or vLLM validation orchestration. No inference server handles the differentiable student rollout.
Checklist Before Submitting
--filesavoids the local Git version's unsupportedls-files --deduplicatepath used by--all-files.AI assistance: Claude and OpenAI via pi assisted implementation, review and test construction. The human submitter understands and owns the change. This remains Draft for upstream architecture review.
Why a dedicated worker/engine instead of the PPO actor/critic/ref workers
The PPO
actor/critic/refroles are three physically separate models, each wrapped by its own FSDP unit, each with its own optimizer, and each occupying its own resource pool. They interact only by passingDataPrototensors (log-probs, values, KL) — there is no shared backbone and, crucially, no shared autograd graph across roles.The DMD-family roles are the opposite: in the recommended
shared_base_adapterslayout,student,fake_score, andstudent_emaare named LoRA adapters on one shared base, andteacher_scoreis that same base with adapters disabled. Within a single student phase they are tightly coupled on the same graph:This requires switching the active role on one physical module while (a) selecting that role's optimizer/scheduler and (b) not disturbing the student's autograd graph. That is exactly what
DistillationRoleGroupEngine.use_roleprovides — and it has no equivalent in the three-independent-model PPO worker topology:activate_roletoggles the adapter (set_adapter, ordisable_adaptersfor the frozen teacher) and re-pointsself.optimizer/lr_scheduler/optimizer_configto that role. Gradient ownership is enforced separately byassert_gradient_isolation, and each stepped role zeroes only its own optimizer.Consequences that the PPO worker stack cannot express without being rebuilt:
DataPrototensor hand-offSo the new worker/engine is not a parallel reimplementation:
DistillationRoleGroupEnginesubclassesDiffusersFSDPEngineand reuses its FSDP1/FSDP2 wrap, LoRA adapter switch/copy/EMA, and export-tensor iteration; the worker subclasses verl'sWorker+DistProfilerExtensionand reuses the Ray lifecycle,EngineRegistry,FSDPCheckpointManagershard format, andDataProtoFuturedispatch. Only the multi-role composition layer (role routing, dual optimizers, alternating cadence, composite checkpoint) is new, because that layer is what the actor-centric single-model/single-optimizer topology cannot represent.Review follow-up: naming propagation
Rebased onto PR 1's naming cleanup:
distillation.control_plane→distillation.controller,distillation.equations→distillation.utils, andDistillationTrainerControlPlane→DistillationTrainerController. All imports, accessors (controller/build_controller), checkpoint save/load paths, and tests were updated accordingly. Newly introduced runtime state uses descriptive snake_case names; framework overrides and Python protocol dunders are unchanged.