[Performance] Keep the DreamerV3 replay write-back off the learner stream - #4307
[Performance] Keep the DreamerV3 replay write-back off the learner stream#4307vmoens wants to merge 2 commits into
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/rl/4307
Note: Links to docs will display an error until the docs builds have been completed. ❌ 11 New FailuresAs of commit 1c19214 with merge base 14324ea ( NEW FAILURES - The following jobs have failed:
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
726f85c to
d1ab7fc
Compare
The GPU estimates remain unmeasured on the profiled node. Faster learner updates should raise collection throughput at a fixed train ratio. |
…ream Profiling a 64-environment DreamerV3 Minecraft run on a 4-GPU node showed one learner update taking 1.37 s with the GPU busy about a quarter of the time. Three CPU-side items stood out: replay_context_update at 18% of the main thread (about 0.25 s per update), the update thread spending 17% of wall time in _validate_conditional_patch, and the prefetch thread spending 13% in sampling. The per-line profile attributes almost all of the first item to the host-to-device copy of the deduplicated index, not to the argsort loop (about 0.5 ms). A pageable copy synchronizes the stream, so the main thread waited for the CUDA-graph step there. The second item is the blocking device-to-host copy of the patch, issued from the update thread after the next graph replay was enqueued: it waited for that replay, and the sample prefetched after the update inherited the delay, which serialized sampling with the learner step. - replay_context_update packs the coordinates into one key and runs a single stable sort (per-column fallback if the key would overflow int64), and moves the kept index to the learner device through pinned memory with non_blocking=True. The main thread no longer synchronizes there. - ReplayBuffer.submit_update_if_present copies CUDA inputs destined for a CPU storage to pinned host memory on the caller's current stream at submission time and records an event; the update thread waits for the event instead of issuing blocking copies. Later work on the stream does not delay the update or the samples that depend on it. - ReplayBufferEnsemble.update_if_present moves the patch to the members' common storage device once and groups the records per member with one stable sort and bincount instead of a boolean mask pass per member. - bench_dreamer_v3_learner.py gains --device cpu and updates_per_second so the replay workload can be timed without CUDA. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
d1ab7fc to
1c19214
Compare
|
Measured on the target hardware (64-environment DreamerV3 Minecraft run, one 4-GPU node, process-slot inference server with a static batch of 64, compiled and CUDA-graph learner step, bf16, train ratio 16), comparing the full stack #4305 + #4306 + #4307 + #4308 (with
The unthrottled collection phase before training reached 1,254 steps/s (298 before), the learner GPU now shows sustained full-utilization bursts instead of about a quarter duty cycle, and the run had no errors over the measured 1.3 hours. The two rates move together because the train ratio couples them, so the stack lifted both the collection ceiling and the learner cadence past the previous limits. This measures the combined effect of the four PRs; per-PR attribution has not been measured. |
Stack: #4305 → #4306 → #4307 → #4308; depends on #4306.
Enqueue CUDA→CPU replay copies at submission; the update thread waits on CUDA events, avoiding copies queued behind the next learner step. Also deduplicate coordinates and group ensemble writes with stable sorts.
Reported validation: CPU DreamerV3/replay tests pass except eight missing-
h5pyfailures. CUDA validation pending.