Skip to content

【No.21】Hybrid-async 多模态可归因性能优化 - #166

Open
Pinoeer-kingxi wants to merge 19 commits into
redai-infra:mainfrom
Pinoeer-kingxi:perf/task21-hybrid-mm-forward-pipeline
Open

【No.21】Hybrid-async 多模态可归因性能优化#166
Pinoeer-kingxi wants to merge 19 commits into
redai-infra:mainfrom
Pinoeer-kingxi:perf/task21-hybrid-mm-forward-pipeline

Conversation

@Pinoeer-kingxi

@Pinoeer-kingxi Pinoeer-kingxi commented Jul 29, 2026

Copy link
Copy Markdown

Summary

Closes #151.

This PR now separates Task 21 into attributable, default-off optimization paths instead of presenting one bundled throughput claim:

  1. Schedule-matched chunk overlap: fetch and run old-policy actor forward on prompt-group-aligned chunks while later rollout groups are still being produced.
  2. ProcessorPool + train-forward log-prob reuse: expose the existing multimodal processor pool in the reference launcher and, under strict true-on-policy guards, reuse detached log-probs from the training forward instead of running a redundant actor log-prob forward.

The rollout batch, sample/token/image work, full-batch advantage domain, and one-update-per-mini optimizer semantics remain unchanged.

Important benchmark scope correction

The existing published GPU evidence is:

  • fixed Qwen3-VL-8B-Instruct;
  • actor TP=2 x CP=2 x DP=1 plus one rollout GPU;
  • four paired seeds in ABBAABBA order;
  • a fresh process for every run;
  • exactly one rollout and one optimizer step per run.

It is therefore a fresh-process first-step benchmark, not steady-state training throughput. The analyzer now records:

measurement_scope=fresh_process_first_step

for --steady-windows 0-0 and emits an explicit claim limit. A steady-state claim requires multi-step runs, excluded warmup, preregistered later windows, and at least two independent runs per condition.

Additional optimizations in this update

  • Parallel multimodal preprocessing: expose the existing ProcessorPool through MM_PROCESSOR_POOL_SIZE in the launcher, making processor concurrency explicit and independently switchable.
  • Train-forward log-prob reuse: under strict true-on-policy guards, reuse detached log-probs from the training forward and skip the redundant actor log-prob forward.
  • Attributable controls: keep ProcessorPool, log-prob reuse, and chunk overlap behind independent environment controls and ablation conditions. Reuse and overlap cannot be enabled together, preventing their performance effects from being conflated.
  • Benchmark scope classification: mark fresh-process, single-step runs as fresh_process_first_step and emit the corresponding claim limit.

Controls and ablations

Condition Environment controls Purpose
B MM_PROCESSOR_POOL_SIZE=0 HYBRID_REUSE_TRAIN_LOGPROBS=0 HYBRID_PIPELINE_FORWARD=0 compatibility baseline
P MM_PROCESSOR_POOL_SIZE=8 HYBRID_REUSE_TRAIN_LOGPROBS=0 HYBRID_PIPELINE_FORWARD=0 ProcessorPool only
P+R MM_PROCESSOR_POOL_SIZE=8 HYBRID_REUSE_TRAIN_LOGPROBS=1 HYBRID_PIPELINE_FORWARD=0 ProcessorPool + train-forward reuse
P+S MM_PROCESSOR_POOL_SIZE=8 HYBRID_REUSE_TRAIN_LOGPROBS=0 HYBRID_PIPELINE_FORWARD=1 ProcessorPool + chunk overlap

The reference launcher rejects HYBRID_REUSE_TRAIN_LOGPROBS=1 together with HYBRID_PIPELINE_FORWARD=1, so their effects cannot be accidentally conflated.

Correctness guards for train-forward reuse

The fast path requires:

  • Hybrid mode and exactly one optimizer mini per rollout partition;
  • deterministic forward behavior (zero attention/hidden/LoRA dropout);
  • no reward KL, KL loss, OPD, old-actor snapshot, rollout-logprob old-policy source, custom before-log-prob hook, or routing replay;
  • TIS when max_staleness > 0;
  • one CP-aligned rollout_log_probs entry per response.

When actor log-probs are intentionally absent, rollout log-probs are used only to construct zero-KL tensors for advantage shape/device compatibility. Reward KL still requires real actor and reference log-probs and fails explicitly if either is missing.

Existing first-step evidence

The prior schedule-matched overlap experiment remains valid within its narrower scope:

Seed Throughput baseline -> overlap Speedup Phase-1 reduction
20260811 597.43 -> 658.46 token/s +10.22% -19.11%
20260812 576.83 -> 647.27 token/s +12.21% -20.33%
20260813 559.25 -> 630.86 token/s +12.80% -23.53%
20260814 569.19 -> 642.15 token/s +12.82% -21.81%

Aggregate paired geometric-mean first-step throughput speedup: 12.01%. This result must not be extrapolated to sustained training throughput.

The frozen replay parity remains unchanged: 1,024 rank-local samples match for tokens, masks, rewards, advantages, returns, multimodal tensors, and dynamic microbatch schedules; loss is identical, maximum log-prob delta is 2.3842e-7, and gradient-norm symmetric relative difference is 0.207%.

Steady-state benchmark protocol

For each B/P/P+R/P+S condition:

  • run at least 40 optimizer steps per fresh process;
  • exclude warmup and preregister later measurement windows;
  • run at least two independent repetitions;
  • keep candidate commit, model/data, seed policy, topology, batch/token limits, image, dependencies, and hardware fixed;
  • report mean, range, per-run values, finite loss/reward/PPO-KL/grad-norm coverage, sample conservation, image count, and optimizer update count.

No new multi-step GPU result is claimed yet. An 8 x RTX A6000 fixed-hardware campaign is queued with the actor on four GPUs at TP2 x CP2 x DP1 and two TP2 rollout engines on four GPUs. Sustained-throughput results will be reported only after all eight B/P/P+R/P+S runs and the preregistered guardrails pass.

Verification

Current head: e2be8cd158609cc2dfae72b7ba92df72cacb3091.

128 passed, 8 skipped

The skips are existing dependency/runtime gates for unavailable local Ray/Megatron components. The following also pass:

  • pre-commit run --all-files --show-diff-on-failure;
  • Ruff check and format;
  • Python compileall;
  • Bash syntax and ShellCheck (excluding the script's existing dynamic-source SC1090/SC1091 diagnostics);
  • git diff --check.

Scope

Changed:

  • guarded Hybrid true-on-policy train-forward log-prob reuse;
  • advantage handling when the dedicated actor forward is intentionally absent;
  • reference launcher controls for ProcessorPool and reuse;
  • benchmark measurement-scope classification;
  • targeted tests and English/Chinese documentation.

Not changed:

  • rollout generation, reward calculation, GRPO grouping, optimizer count, checkpoint/data formats, or dependencies;
  • owner/ref multimodal payload transport;
  • the existing schedule-replay and TransferQueue correctness contracts.

@xiaoliang0601

Copy link
Copy Markdown
Contributor

Hi @Pinoeer-kingxi ,是否还要进一步验收和整理代码?我看当前还是 Draft 状态。

Gate a fixed sample-window actor-forward path behind an explicit switch so multimodal fetch and log-prob work can overlap later rollout production without changing full-batch GRPO or optimizer semantics.

Constraint: The first release is limited to actor-only multimodal Hybrid GRPO on TP2/DP1/PP1/VPP1/CP2/EP1/ETP1 with offload and dropout disabled.
Rejected: bind actor chunks to physical producer puts | FIRST_COMPLETED, tail flush, and backfill make put grouping dynamic.
Rejected: token-budget drain or actor prefetch threads | they widen correctness and collective-order risk before the fixed-window path is measured.
Confidence: medium
Scope-risk: moderate
Directive: Do not widen topology or claim performance until frozen-input parity, 8-GPU smoke, and paired A/B satisfy Issue redai-infra#151.
Tested: 94 host tests with 3 dependency-gated skips; 103 fixed-image tests including actor wiring and TransferQueue regressions; pre-commit all files.
Not-tested: 8-GPU multimodal smoke, frozen-input parity, and 2x baseline/2x experiment measurements because the pinned dataset and eight simultaneously idle GPUs are unavailable.
Exercise the five-file plot contract without forcing the optional plotting
stack into the minimal CI environment, and fail clearly when real benchmark
plotting is requested without matplotlib.

Constraint: GitHub's core Python test image intentionally omits matplotlib.
Rejected: Add matplotlib to core test dependencies | it would expand the default environment for a benchmark-only output path.
Confidence: high
Scope-risk: narrow
Directive: Keep requested benchmark artifacts fail-fast; never silently return an empty plot bundle.
Tested: 101 passed and 3 skipped on host; 104 passed in the fixed Relax image; pre-commit run --all-files.
Not-tested: 8-GPU multimodal smoke and paired performance A/B remain pending on the pinned dataset and idle topology.
Argparse interpolates percent signs while rendering help, so keep the preregistered target text literal and lock the public help path with a regression test.

Constraint: Benchmark operators must be able to inspect the exact acceptance targets before launching expensive 8-GPU runs.
Rejected: Removing percentages from help | That would hide the preregistered thresholds rather than fixing the CLI contract.
Confidence: high
Scope-risk: narrow
Directive: Keep argparse help strings safe for percent interpolation and cover --help as an executable interface.
Tested: 26 analyzer tests; 96 related host tests with 3 Megatron-only skips; 99 related tests in the fixed Relax image; targeted pre-commit hooks; direct --help smoke.
Not-tested: 8-GPU Hybrid-async end-to-end smoke remains pending idle capacity.
Use one shape-aware slicer for live-equivalent debug chunks so tensor, NumPy, tuple, and list fields stay aligned during off/on frozen-input parity.

Constraint: Frozen replay must exercise the same 128-sample partitioning without duplicating unsliced per-sample arrays.
Rejected: Converting every debug field to Python lists | That would change dtype/container semantics and hide replay mismatches.
Confidence: high
Scope-risk: narrow
Directive: Route future debug-rollout partitioning through the shared shape-aware slicer and test new per-sample container types.
Tested: 96 related host tests with 4 Megatron-only skips; 106 related tests in the fixed Relax image; targeted pre-commit hooks; py_compile; git diff --check.
Not-tested: 8-GPU Hybrid-async smoke remains gated on all eight GPUs becoming idle.
…edits

Expose validated, default-preserving model, resource, length, checkpoint, and output controls so paired multimodal runs can be reproduced without temporary launcher rewrites.

Constraint: Preserve the existing Qwen3.5 8-GPU recipe by default.

Rejected: Maintain external text-replacement overlays | brittle across launcher changes and cannot reliably propagate MetricsService output paths.

Confidence: high

Scope-risk: moderate

Directive: Keep benchmark controls opt-in and compare only identical workload configurations.

Tested: bash -n; shellcheck; 99 related pytest cases passed with 4 environment skips.

Not-tested: Registered 8-GPU Qwen3.5 E2E is pending an uncontended 8-GPU window.
Use the rollout-side truncation ratio and require paired runs to match the complete model, data, length, resource, deterministic-inference, and debug workload configuration before computing statistics. Keep TensorBoard parsing usable with newer host protobuf runtimes.

Constraint: Task 21 evidence must compare identical workloads and report an actual truncation rate.

Rejected: Rely only on matching commit and batch sizes | model, context, and GPU topology mismatches can still invalidate the result.

Confidence: high

Scope-risk: narrow

Directive: Extend COMPARISON_WORKLOAD_MANIFEST_FIELDS whenever the benchmark runner adds a behavior-affecting setting.

Tested: 100 relevant pytest cases passed, 4 environment-dependent cases skipped; ruff, py_compile, bash -n, shellcheck with source exclusions, git diff --check; host smoke-pair analysis passed.
Expose prompt-aligned stage count without changing the default recipe, and require paired deterministic runs to prove identical samples, workload, static inputs, and successful exits before accepting performance targets.

Constraint: Task 21 must support a four-stage 256-sample mini and reproducible paired first-step evidence on the available five-GPU topology.

Rejected: Accept aggregate workload within one percent under deterministic inference | it can hide different samples or generated lengths.

Confidence: high

Scope-risk: narrow

Directive: Keep baseline and experiment NUM_ITERS_PER_TRAIN_UPDATE identical and label window 0-0 as fresh-process first-step evidence.

Tested: 104 relevant pytest cases passed, 4 environment-dependent cases skipped; ruff, py_compile, bash -n, shellcheck warning gate, git diff --check.
Require the formal analyzer to observe four equal producer puts, and reject paired results captured on different hosts or GPU inventories.

Constraint: The claimed optimization is a four-by-64 producer/actor pipeline measured on one fixed hardware topology.

Rejected: Treat producer put grouping as diagnostic in the formal protocol | actor-only chunk evidence does not prove end-to-end staging.

Confidence: high

Scope-risk: narrow

Directive: Pass --expected-producer-chunks only for protocols that pre-register producer grouping.

Tested: 105 relevant pytest cases passed, 4 environment-dependent cases skipped; ruff, py_compile, bash -n, shellcheck warning gate, git diff --check.
Replay each chunk's dynamic microbatch schedule during the single merged optimizer step so batch-shape-dependent BF16 rounding cannot create a false PPO ratio before weights change.

Constraint: Hybrid overlap remains limited to actor-only dynamic batching with one optimizer mini and TP2/CP2/DP1.

Rejected: Recompute one full-batch training schedule | It changes packed kernel shapes relative to old-policy forward and produced artificial KL.

Confidence: high

Scope-risk: moderate

Directive: Keep old-policy and training-forward microbatch grouping identical when extending supported topologies.

Tested: 111 targeted pytest passed, 4 dependency-gated skipped; Ruff check/format, py_compile, bash -n, git diff --check.

Not-tested: Full GPU frozen-rollout parity is run immediately after this commit.
Add a no-overlap control that fetches every identical actor chunk before forwarding while preserving chunk-local dynamic schedules and one merged optimizer update. Benchmark validation now proves the requested ordering and rejects same-weight PPO KL or clipping drift.

Constraint: Formal Task 21 comparisons must differ only by hybrid_pipeline_overlap; both arms use chunk forwarding.

Rejected: Use the legacy full-batch flag-off path as the performance baseline | Its different packed microbatch shapes confound overlap with BF16 numerical and kernel-shape effects.

Confidence: high

Scope-risk: moderate

Directive: Keep the no-overlap arm schedule-identical whenever chunk execution or topology support changes.

Tested: 119 targeted pytest passed, 5 dependency-gated skipped; Ruff check/format, py_compile, bash -n, shellcheck error-level, git diff --check.

Not-tested: Frozen GPU no-overlap versus overlap parity and formal paired throughput runs follow this commit.
Apply the repository docformatter layout so local and GitHub pre-commit checks produce no working-tree mutation.

Constraint: The project-wide pre-commit job requires docformatter-idempotent docstrings.

Rejected: Disable or bypass docformatter | That would weaken an existing repository gate.

Confidence: high

Scope-risk: narrow

Directive: Run the repository pre-commit hooks, not only Ruff, when editing docstrings.

Tested: pre-commit on the changed file; 119 targeted pytest passed with 6 dependency-gated skips; git diff --check.
Constraint: Upstream no longer imports contextlib.nullcontext in actor.py
Confidence: high
Scope-risk: narrow
Tested: 121 targeted tests; Ruff; compileall; pre-commit; shell syntax and ShellCheck
Not-tested: final 5-GPU parity and ABBA pending idle GPUs
@Pinoeer-kingxi
Pinoeer-kingxi force-pushed the perf/task21-hybrid-mm-forward-pipeline branch from b0f716b to 78d3fe0 Compare August 11, 2026 09:19
The producer may expose prompt-group-aligned puts with unequal sizes while the actor still consumes the fixed registered schedule. Validate event closure, aggregate samples, and fingerprints instead of coupling producer puts to actor chunks.

Constraint: Producer completion order can yield 64,64,72,56 for a valid 256-sample rollout.
Rejected: Require four equal producer puts | async producer grouping is not part of the actor-forward contract.
Confidence: high
Scope-risk: narrow
Directive: Keep actor chunk counts strict; producer put counts remain diagnostic.
Tested: 33 analyzer tests; Ruff on changed Python; git diff --check
Not-tested: Full GPU benchmark reruns after this analyzer-only correction
Publish the preregistered four-pair benchmark curves and compact data, and render quality guardrails by paired seed so one-step runs remain interpretable.

Constraint: Formal training evidence was collected at parent commit 780c742 on physical GPUs 1,2,3,4,6.
Rejected: Rerunning eight successful GPU jobs after an analyzer-only presentation change | the performance path is unchanged and the existing raw artifacts were reanalyzed successfully.
Confidence: high
Scope-risk: narrow
Directive: Keep performance claims tied to the immutable raw manifests and disclose asynchronous microbatch-order effects separately from deterministic replay parity.
Tested: 33 analyzer tests; ruff check; git diff --check; formal analyzer --enforce-targets passed on 8 real GPU runs.
Not-tested: No additional GPU training was run after this analyzer/report-only commit.
@Pinoeer-kingxi
Pinoeer-kingxi marked this pull request as ready for review August 11, 2026 13:51
Apply the repository's current ruff-format normalization so pre-commit remains clean on the published evidence commit.

Constraint: GitHub pre-commit uses a newer formatter than the host ruff binary.
Confidence: high
Scope-risk: narrow
Tested: ruff format; ruff check; git diff --check.
Not-tested: No behavior test was repeated for a formatting-only change.
@Pinoeer-kingxi

Copy link
Copy Markdown
Author

已完成进一步验收和代码整理,PR 现已转为 Ready:

Flatten real and fake subplot grids through their public iterable shape and extend the minimal CI plotting double for the new quality panel.

Constraint: CI intentionally exercises the analyzer with a lightweight matplotlib substitute.
Rejected: Requiring matplotlib in the unit-test image | plotting remains an optional benchmark dependency.
Confidence: high
Scope-risk: narrow
Tested: 33 analyzer tests with matplotlib forced absent; ruff format/check; git diff --check.
Not-tested: GPU training is unaffected and was not repeated.
@Pinoeer-kingxi

Copy link
Copy Markdown
Author

补充:当前 head 3a1c9f88d0b4b187545bd95e3dd68643c0ef1e55 的 CI 已全部通过:Lint、Pre-commit Checks、Python 3.10/3.11/3.12 Tests 均为绿色。

@Pinoeer-kingxi

Copy link
Copy Markdown
Author

您好@xiaoliang0601 ,我已更新,麻烦您验收一下

@xiaoliang0601

Copy link
Copy Markdown
Contributor

收益部分:现有 benchmark 是固定 Qwen3-VL、TP2×CP2×DP1 拓扑下的四组 fresh-process、单 optimizer-step 运行。它更接近 first-step benchmark,而不是稳态训练吞吐。

效果部分:感觉没有完全对齐,甚至差得有点大。

@Pinoeer-kingxi

Copy link
Copy Markdown
Author

好的明白,我接下来进行优化

# ⚡ Performance

## Reuse deterministic train-forward log probabilities

- Skip the redundant Hybrid actor log-prob forward in guarded true-on-policy runs
- Validate single-mini, TIS, dropout, KL, routing, and context-parallel alignment contracts
- Expose the existing multimodal ProcessorPool through the reference launcher

---

# 🐛 Bug Fix

## Preserve true-on-policy advantage semantics

- Use rollout log-probabilities only to construct zero-KL tensors when actor log-probabilities are intentionally absent
- Fail explicitly when reward KL lacks actor or reference log-probabilities

---

# 📝 Documentation

## Bound the published performance claim

- Label the existing four paired single-step runs as fresh-process first-step evidence
- Record measurement scope in analyzer output and document multi-step steady-state requirements
- Keep ProcessorPool, log-prob reuse, and chunk overlap as separate cumulative ablations

---

# ✅ Tests

## Cover reuse guards and benchmark scope

- Verify launcher defaults, supported switches, and incompatible combinations
- Exercise zero-KL advantage construction and measurement-scope classification

Constraint: Existing Qwen3-VL TP2 x CP2 x DP1 evidence contains one optimizer step per fresh process
Rejected: Bundle owner/ref group payload dedup | PR redai-infra#201 reported a paired-mean samples/s regression for that mechanism
Confidence: high
Scope-risk: moderate
Directive: Keep train-logprob reuse and chunk overlap as separate ablations until multi-step GPU evidence supports combining them
Tested: 128 pytest cases passed with 8 dependency-gated skips; pre-commit run --all-files passed; Ruff, compileall, Bash, ShellCheck, and git diff checks passed
Not-tested: Real multi-step GPU steady-state training because no Ray cluster address was provided
@Pinoeer-kingxi Pinoeer-kingxi changed the title 【No.21】Hybrid-async 多模态固定窗口 actor-forward 流水线 【No.21】Hybrid-async 多模态可归因性能优化 Aug 14, 2026
Treat an empty nvidia-smi topology match as a valid zero-NVLink configuration so the Ray-job entrypoint can reach the training launcher.\n\nConstraint: The benchmark host uses A6000 GPUs without NVLink and the entrypoint runs with pipefail.\nRejected: Requiring an NVLink topology or disabling pipefail | would exclude the actual benchmark hardware or weaken unrelated failure detection.\nConfidence: high\nScope-risk: narrow\nDirective: Preserve the explicit no-NVLink fallback when changing topology detection.\nTested: bash -n; targeted launcher and actor tests (9 passed, 7 skipped); pre-commit; git diff --check.\nNot-tested: Full multi-GPU training was blocked by the pre-fix entrypoint failure and will be rerun after this commit.
Add a fail-closed four-condition steady campaign protocol while preserving the existing first-step comparison surface. Treat train-forward reuse as an intentional absence of the dedicated actor forward in trace validation.

Constraint: PR 166 requires B/P/P+R/P+S runs with 40 optimizer steps, warmup exclusion, paired seeds, fixed TP2xCP2xDP1 hardware, and real NVML evidence.

Rejected: Reusing the baseline/experiment target gate | it conflates independent optimizations and rejects the reuse trace contract.

Confidence: high

Scope-risk: moderate

Directive: Keep first-step and steady-state claim scopes separate; do not accept incomplete seed-condition matrices.

Tested: 38 analyzer tests; Ruff check/format; targeted pre-commit hooks; git diff --check.

Not-tested: Real eight-run GPU campaign is started only after this clean commit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Task 21][Hybrid-Async] 固定样本窗口流水化 actor forward,消除整批多模态等待

2 participants