Rework AsyncGRPO metrics metrics and docs - #6715
Conversation
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
| self._last_step_end_time = time_after | ||
| self._current_train_step_time = 0.0 | ||
| self._step_forward_s = 0.0 | ||
| self._step_optimizer_s = 0.0 |
There was a problem hiding this comment.
Optimizer time logged one step late
Medium Severity
_log_step_metrics runs at the end of the last training_step micro-batch, before optimizer.step(). It flushes and resets perf/optimizer_s while _OptimizerTimeCallback only records the optimizer afterward, so each step logs the previous step's optimizer time and the final step's value is never logged.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 36bbf31. Configure here.
| "rollout/generated_tok_s": ( | ||
| float(self._total_completion_tokens - self._pushed_completion_tokens), | ||
| now - self._pushed_at, | ||
| ), |
There was a problem hiding this comment.
Generated throughput counts trained tokens
Medium Severity
rollout/generated_tok_s is fed from _total_completion_tokens, which sums completion_mask over reconciled sequences. After a realign, generated tokens demoted to context are excluded, so the metric under-reports generation throughput relative to the PR's generated-vs-trained definitions and to completions/mean_length.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 36bbf31. Configure here.
| # Only meaningful when the model has tools to call: with none, the loop always ends on the first turn and | ||
| # the metric would be a constant 0 cluttering every run that does not use tools. | ||
| self._rates["tools/loop_exhausted_frac"][0] += loop_exhausted | ||
| self._rates["tools/loop_exhausted_frac"][1] += 1 |
There was a problem hiding this comment.
Harness timeout metric never recorded
Low Severity
OpenEnv passes loop_exhausted=timed_out into _push_rollout_metrics, but that rate is only updated when self.tools is truthy. Harness sessions do not populate self.tools, so tools/loop_exhausted_frac stays absent for timed-out OpenEnv rollouts.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 36bbf31. Configure here.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…mple's Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
There are 5 total unresolved issues (including 3 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 094a214. Configure here.
| # An empty queue with the trainer waiting is generation-bound; a full queue with no wait is trainer-bound | ||
| # (and then `rollout/backpressure_s` is what generation lost to it). | ||
| self.metrics["sample/rollout_queue_size"].append(float(self.queue.qsize())) | ||
| self.metrics["sample/time_in_queue_s"].append(now - sample.enqueued_at) |
There was a problem hiding this comment.
Unset enqueue time skews queue wait
Medium Severity
sample/time_in_queue_s is always now - sample.enqueued_at. enqueued_at defaults to 0.0 and is only set by the built-in worker’s put_nowait path, so custom workers and _StubRolloutWorker report queue waits of about 1.7e9 seconds.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 094a214. Configure here.
… stub Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>


What does this PR do?
Async GRPO has more places to be slow than sync GRPO: generation, scoring, the queue between the worker and the trainer, weight sync.
The current metric set can't tell you which one is the problem. This PR restructures the metrics around where a number is measured, fixes the reductions, and adds a "Logged metrics" section to the docs explaining what each one means and how to read them together. A rollout passes through several stages before it becomes a gradient:
So I added more metrics based on these entities:
rollout/completions/tools/sample/batch/perf/Renames
Anyone with a dashboard on this trainer will need to update it:
training_tok/sperf/forwarded_tok_s_fwd_bwd,perf/forwarded_tok_s_wall_clock,perf/trained_tok_s_wall_clockstep_timeperf/fwd_bwd_siteration_time_sperf/step_sforward_time_sperf/fwd_sweight_sync_time_sperf/weight_sync_s(+_pause_s,_barrier_s,_transfer_s)queue_wait_time_sperf/rollout_wait_sandsample/time_in_queue_sgeneration_tok_per_srollout/generated_tok_s(windowed, not cumulative)scoring_time_ms,wait_scoring_msrollout/score_s,rollout/score_wait_sbuffer_qsizesample/rollout_queue_sizetrain_seq_lensample/forwarded_tokens_meanandbatch/row_tokens_meanratio,kl,entropy,clip_ratio/*,aux_loss,completions/mean_length,reward,reward_std,rewards/<func>,tools/call_frequencyandtools/failure_frequencykeep their names.queue_wait_time_sis the one worth calling out: it was used for two opposite things — the trainer blocked because the queue was empty, and a sample's own time sitting in it. Those diagnose opposite bottlenecks, so they are now two metrics.Note
Medium Risk
Large change to logging contracts and
RolloutWorkerProtocol(custom workers must exposemetrics_queue); dashboards need metric renames, but training logic changes are mostly observability and aggregation paths.Overview
Async GRPO observability is rebuilt so you can tell whether generation, scoring, the rollout queue, or training is the bottleneck. Metrics are grouped by entity (
rollout/,completions/,tools/,sample/,batch/,perf/) and documented in a new Logged metrics section indocs/source/async_grpo_trainer.md.Reduction and naming fixes:
_reduce_metricinfers sum/mean/max/min and Σnum/Σden for rates (fixing broken throughput like the oldtraining_tok/s).queue_wait_time_ssplits intoperf/rollout_wait_s(trainer starved) vssample/time_in_queue_s(per-sample age). Throughput/MFU are reported on_fwd_bwdand_wall_clockbases; weight sync is broken into phase timings underperf/weight_sync_*.Instrumentation plumbing: The rollout worker pushes metrics through a bounded
metrics_queueonRolloutWorkerProtocol; the trainer drains it inlog(). The worker logs rollout/scoring/queue backpressure, tool stats, drift/fork tallies from_chain_to_sequences, and windowedrollout/generated_tok_s. The trainer/collator log batch packing (row_fill_frac,pad_frac, token counts), staleness drops, optimizer time via_OptimizerTimeCallback, and per-step aggregates in_log_step_metrics. Per-sample rewards are aggregated on rank 0 in the collator instead of broadcasting metric tensors. Rollout trace logging is throttled per policy version to avoid flooding dashboards.Tests cover
_reduce_metric, worker metric push, protocolmetrics_queue, collator metric keys, and drift tally behavior.Reviewed by Cursor Bugbot for commit 4a4a1ae. Bugbot is set up for automated code reviews on this repo. Configure here.