Skip to content

feat(checkpoint): trace batch age - #5049

Open
macandro96 wants to merge 2 commits into
mainfrom
amahishi/rollout-trace-batch-age
Open

macandro96 wants to merge 2 commits into
mainfrom
amahishi/rollout-trace-batch-age

Conversation

@macandro96

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds batch age to the rollout trace: the token-weighted number of policy updates between generating a token and training on it, per training step.

Stacked on #5048 (the rollout event log).

How it works

  1. Per group: the reassembler returns each trained model call's ID, the weight version it began on and the tokens it generated. At publish, the controller writes a group_published event that sums tokens by version.
  2. Per step: step_trained also records the policy version the step updated.
  3. Exact at refits: vLLM keeps running calls across a refit, so a call's later tokens come from the new weights. While generation is paused for a refit, the vLLM worker reports how many tokens each running captured call has generated so far, written as a refit_cut event. group_published lists those calls individually so the analysis can split them; all other calls arrive summed by version.
  4. Offline: batch_age_by_step in rollout_checkpointing/trace.py computes each step's batch age; python -m nemo_rl.algorithms.rollout_checkpointing.trace <log_dir>/rollout_trace.jsonl prints it.

The two commits separate the per-version count (exact except for calls that span a refit) from the exact refit split.

Notes for review

  • vLLM internals: the running token count comes from vLLM's output-processor request state, which has no public API (external_req_id, detokenizer.num_output_tokens(), as in vLLM 0.29). An engine without that state reports nothing, and those calls count under the version they began on. Other backends inherit a default that reports nothing.
  • Request-to-call link: a context variable set when capture begins a call, read where the same request task submits it to the engine.
  • Overlap with feat(checkpoint): recover active vLLM generation prefixes #4506: the second commit touches vllm_worker_async.py, the generation interface and vllm_generation.py, which feat(checkpoint): recover active vLLM generation prefixes #4506 also changes; whichever lands second needs a small rebase there.
  • Nothing Gym stores or a checkpoint saves changes.

Testing

  • Unit: controller and analysis tests (split across two refits, an interrupted refit, token weighting, the refit and publish events), two vLLM wrapper tests (run in vLLM 0.29's venv), and the 20-turn capture pipeline test checks the token counts. 2116 passed (default lane), 121 passed (Gym lane). ruff and pyrefly clean.
  • GPU: a Gym run with continuous dispatch traced 6 steps (batch age 0.0, 1.0, 1.09, 1.27, 1.28, 1.15). One refit paused a call before its first token; the trace counted its 60 tokens under the new weights ({v1: 60, v0: 30}), where counting by start version gives {v0: 90}.

🤖 Generated with Claude Code

@copy-pr-bot

copy-pr-bot Bot commented Nov 3, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions github-actions Bot added the Documentation Improvements or additions to documentation label Nov 3, 2026
@macandro96
macandro96 added this pull request to stack #5057 November 3, 2026 23:39
@macandro96
macandro96 requested a review from terrykong November 4, 2026 00:12
@terrykong terrykong added the CI:Lfast Runs a fast test suite and re-use nightly `main` container (but sync dependencies to PRs version) label Nov 5, 2026
Base automatically changed from amahishi/rollout-trace to main November 6, 2026 19:36
macandro96 and others added 2 commits November 6, 2026 12:17
Batch age is the token-weighted number of policy updates between generating
a token and training on it. With token capture and the rollout trace on:
- the reassembler returns each finalized group's tokens by the weight version
  each trained call began on;
- the controller writes them in a group_published event, and step_trained
  also records the policy version the step updated.

batch_age_by_step in rollout_checkpointing/trace.py computes each step's
batch age, and `python -m nemo_rl.algorithms.rollout_checkpointing.trace
<file>` prints it. A call that runs across a refit counts under the version
it began on, so it counts as slightly older than it is.

Source: +80 / -1. Tests: +67 (2 new tests, and the 20-turn capture pipeline
test checks the token counts). Docs: +12 / -1.
Unit: 2111 passed (default lane), 121 passed (Gym lane). ruff and pyrefly
clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Anish Mahishi <amahishi@nvidia.com>
Token capture stamps each model call with the weight version it began on, but
vLLM keeps running calls across a refit, so a call's later tokens come from
the new weights. Batch age counted them under the call's start version.

With the rollout trace and token capture on:
- each refit, while generation is paused, writes a refit_cut event: for every
  running captured call, how many tokens it has generated on the weights
  being replaced. The vLLM worker links each engine request to its captured
  call through a context variable set when capture begins the call, and reads
  the token count from vLLM's output-processor request state, which has no
  public API; an engine without that state, or another backend, reports
  nothing;
- the reassembler returns each trained call's ID, start version and tokens,
  and group_published sums them by version but lists on their own the calls
  a refit paused;
- tokens_by_version splits those calls at their refits, and batch_age_by_step
  uses the split.

Nothing Gym stores or a checkpoint saves changes.

Source: +196 / -41. Tests: +280 / -56 (vLLM wrapper tests and refit-split
tests). Docs: +10 / -5.
Unit: 2116 passed (default lane), 121 passed (Gym lane); the vLLM wrapper
tests pass in vLLM 0.29's venv. ruff and pyrefly clean. On a GPU Gym run, a
call a refit paused before its first token was counted under the new
weights.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Anish Mahishi <amahishi@nvidia.com>
@macandro96
macandro96 force-pushed the amahishi/rollout-trace-batch-age branch from c2bf309 to 09627ac Compare November 6, 2026 20:20

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI:Lfast Runs a fast test suite and re-use nightly `main` container (but sync dependencies to PRs version) Documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants