Skip to content

Log weight-sync time as a streaming-trainer metric#560

Merged
jlamypoirier merged 2 commits into
mainfrom
jlp_weight_sync_time
Jul 8, 2026
Merged

Log weight-sync time as a streaming-trainer metric#560
jlamypoirier merged 2 commits into
mainfrom
jlp_weight_sync_time

Conversation

@jlamypoirier

Copy link
Copy Markdown
Collaborator

What

The streaming trainer callback broadcasts the full model to the inference actor on every successful step — synchronously, inside the training loop (so it's part of step_time_ms) — but nothing measured how long that takes. This logs it as weight_sync_time_ms, so the share of step time spent shipping weights is visible in the training logs and W&B.

Part of the RL-diagnostics initiative (making the Fast-LLM trainer the single source of truth for RL metrics); shipped as an independent PR since it's self-contained and touches no wire schema.

How

  • Timing: bracket the broadcast (iter_checkpoint ZeRO-gather + NCCL push) with CUDA events on the broadcasting rank. The result is read one step later (_weight_sync_pending + Event.query()), so the always-on timer never forces a CPU stall — the broadcast otherwise overlaps the next step's compute, and reading elapsed_time immediately would serialize them. broadcast() runs with async_op=False (work.wait()), so the current stream is ordered after the transfer and the end event captures true completion. The CPU/gloo broadcast path (non-NCCL) falls back to a plain perf_counter measurement, which needs no deferral.
  • Plumbing: TrainerCallback.step_end may now return a dict[str, Any] | None of scalar metrics; the trainer merges any returned dicts into the step's training metrics alongside **train_metrics. Base callback returns None.
  • Scope is trainer-side broadcast only — actor receive/load time is out of scope.

Cost

Zero on the disabled path (non-streaming runs never construct the callback). On the streaming path: two reusable CUDA events and one deferred elapsed_time read per logging step — negligible against a full-model gather+broadcast, and no added GPU sync.

Testing

No unit test: the path requires a live Redis + external-world rendezvous + CUDA, there's no streaming-callback test harness, and the only logic is the CUDA-event deferral state machine. Verified imports + black locally; the metric is validated on a live streaming RL run (the new key appears under training/*).

🤖 Generated with Claude Code

jlamypoirier and others added 2 commits July 8, 2026 15:11
The streaming callback broadcasts the full model to the inference actor on
every successful step, synchronously inside the training loop, but nothing
measured how long it took. Time it and log `weight_sync_time_ms` so the share
of step time spent shipping weights is visible in the training logs and W&B.

Timing uses CUDA events read one step later, so the always-on timer adds no
CPU sync on the broadcast (which otherwise overlaps the next step's compute);
the CPU/gloo broadcast path falls back to a plain wall-clock measurement.
Callbacks may now return a metrics dict from `step_end`, merged into the
step's training metrics.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tention

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant