Skip to content

[diffusion, trainer, tests] feat: strip responses from worker batches - #430

Merged
zhtmike merged 1 commit into
verl-project:mainfrom
WenzheWang:wenzhe/strip-unused-responses
Aug 24, 2026
Merged

zhtmike merged 1 commit into
verl-project:mainfrom
WenzheWang:wenzhe/strip-unused-responses

Conversation

@WenzheWang

@WenzheWang WenzheWang commented Aug 23, 2026 •

Copy link
Copy Markdown
Collaborator

What does this PR do?

Implements Phase 1 of #386 by excluding driver-only responses pixels from diffusion actor, reference, teacher, and old-log-prob worker payloads while retaining the original DataProto for reward scoring, evaluation, and logging.

  • Adds one shallow DataProto → TensorDict projection that removes only responses without copying tensor storage.
  • Applies the projection to the v0 policy-gradient/direct-preference paths and the equivalent v1 trainer paths.
  • Adds CPU contracts for field removal, driver ownership, shared tensor storage, metadata preservation, and every affected production entry point.

This complements #373, which implemented the separate uint8 response representation phase. AI assistance was used for this change, and the final diff received human review before publication.

Checklist Before Starting

  • Searched for similar PRs: open PRs referencing #386 and exact head WenZheWang:wenzhe/strip-unused-responses; no duplicate found.
  • Formatted the PR title as [{modules}] {type}: {description} and validated it with tests/special_sanity/check_pr_title.py.

Test

pytest -q tests/trainer/diffusion
175 passed, 4 warnings

pre-commit run --files \
  verl_omni/trainer/diffusion/ray_diffusion_trainer.py \
  verl_omni/trainer/diffusion/v1/trainer_base.py \
  tests/trainer/diffusion/test_worker_batch_projection_on_cpu.py
all hooks passed

The CPU suite ran on macOS with an import-only stub for the optional vLLM rollout package because vLLM is unavailable on macOS; the production trainer modules and methods were exercised.

Hardware validation on exact head ba3918cfb4e2a2bca9120ded699b2e52ddf9ba50:

  • CPU Ray transport benchmark (torch 2.6.0+cu124, Ray 2.53.0): batch 8, 192 frames, 512×512 RGB uint8 responses, 2 warmups and 8 measured repetitions per arm. Tensor payload fell from 1,224,737,280 to 16,777,728 bytes (98.63% reduction); median end-to-end transfer time fell from 1.64636 s to 0.03249 s (98.03% reduction). The driver retained responses, the projected worker payload excluded it, and all predeclared gates passed.
  • One-A800 deterministic GPU smoke (NVIDIA A800 80GB PCIe, CUDA 12.4, torch 2.6.0+cu124, Ray 2.53.0): seed 42, six optimizer steps per arm. Tensor payload fell from 402,784,288 to 131,104 bytes (99.967% reduction); baseline and projected loss sequences were identical, maximum absolute loss and parameter differences were both 0.0, and final parameter SHA256 values matched. All eight predeclared correctness gates passed.

The hardware evidence is intentionally scoped to response-payload transport and deterministic optimizer equivalence. It does not claim end-to-end diffusion quality, full-model production throughput, or multi-GPU semantics.

API and Usage Example

No public API, configuration, or user workflow changes. Diffusion trainer call sites automatically omit responses only when preparing actor/ref worker payloads.

Design & Code Changes

  1. DataProto.to_tensordict() creates the worker-side container while preserving references to existing tensor storage.
  2. The projection removes responses from that container only; the driver-side DataProto remains unchanged.
  3. All v0/v1 actor update, reference/teacher inference, and old-log-prob entry points reuse the same projection before RPC dispatch.
  4. Tests assert the worker payload excludes pixels while all other tensor, non-tensor, and metadata contracts remain intact.

Checklist Before Submitting

  • Read the Contribute Guide and repository agent instructions.
  • Applied pre-commit checks; all hooks passed for the changed files.
  • Documentation is unchanged because this is an internal transport optimization with no API, configuration, or usage change.
  • Added test_worker_batch_projection_on_cpu.py; existing CPU workflow discovery covers tests/trainer/diffusion/*_on_cpu.py, so no workflow edit is required.

Avoid transporting driver-only response pixels to diffusion actor, reference, teacher, and old-log-prob RPCs while retaining the original DataProto for reward and logging paths. Add CPU contracts for the v0 and v1 trainer entry points and shallow tensor projection.

AI assistance was used for this change.

Signed-off-by: Wenzhe Wang <w_wenzhe@163.com>
@WenzheWang
WenzheWang marked this pull request as ready for review August 23, 2026 11:42
@knlnguyen1802 knlnguyen1802 added the ready-for-ci read for running CI label Aug 24, 2026
@knlnguyen1802

Copy link
Copy Markdown
Collaborator

cc: @wtomin Do you think we need the run L3 nightly CI for this ?

@zhtmike

zhtmike commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

if possible, pls add a sd3 reward curve for this pr

@WenzheWang

Copy link
Copy Markdown
Collaborator Author

Thanks @zhtmike. I ran a paired 20-step SD3/PickScore reward-curve check on the exact PR head ba3918cfb4e2a2bca9120ded699b2e52ddf9ba50 against main a1139bafffb5b9711f0a6b6edff8ecaa60bfff30.

Setup: 1× NVIDIA A800 80GB, fixed tiny random SD3 checkpoint, real cached PickScore v1 reward, seed 42, 3 prompts, 2 responses per prompt, 12 images/step, 256×256, and 20 optimizer steps. main, PR, and main_repeat ran sequentially in the same allocation with the same data and configuration; main_repeat is the same-code jitter control.

Step main PR #430 main repeat
1 0.75898719 0.75898641 0.75898677
2 0.76831549 0.76841182 0.76844853
3 0.76590484 0.76577920 0.76578778
4 0.75590605 0.75588411 0.75581431
5 0.75350398 0.75340390 0.75341350
6 0.77307081 0.77297622 0.77302748
7 0.75445849 0.75441766 0.75449592
8 0.76031065 0.76028061 0.76056117
9 0.77247518 0.77255607 0.77244782
10 0.74381357 0.74377900 0.74379188
11 0.76739496 0.76732469 0.76721960
12 0.77219492 0.77234393 0.77220815
13 0.76181728 0.76195306 0.76193595
14 0.74551183 0.74545336 0.74554199
15 0.76090670 0.76067001 0.76076955
16 0.75968319 0.75963181 0.75946850
17 0.75559473 0.75549245 0.75563931
18 0.75373650 0.75358707 0.75360852
19 0.77402228 0.77396125 0.77397227
20 0.76185465 0.76187211 0.76177162

Comparison against main:

  • PR: max absolute delta 2.3669e-04, mean absolute delta 8.2874e-05, Pearson 0.999945
  • Same-code repeat: max absolute delta 2.5052e-04, mean absolute delta 9.0396e-05, Pearson 0.999917

The predeclared gate required three finite 20-point curves and PR max/mean deltas no greater than the same-code control plus 5e-05 (limits: 3.0052e-04 / 1.4040e-04). The result passes: the PR curve stays within the observed same-code jitter.

Scope: this is a paired mechanism-level SD3/PickScore conformance check. Because it uses a tiny random SD3 checkpoint, it does not claim pretrained SD3.5 quality/convergence, production throughput, or multi-GPU performance.

@zhtmike

zhtmike commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Thanks~

@zhtmike
zhtmike merged commit 86e1753 into verl-project:main Aug 24, 2026
13 checks passed
SelfDLer pushed a commit to SelfDLer/verl-omni that referenced this pull request Aug 26, 2026
…verl-project#430)

Avoid transporting driver-only response pixels to diffusion actor, reference, teacher, and old-log-prob RPCs while retaining the original DataProto for reward and logging paths. Add CPU contracts for the v0 and v1 trainer entry points and shallow tensor projection.

AI assistance was used for this change.

Signed-off-by: Wenzhe Wang <w_wenzhe@163.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-ci read for running CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants