[Performance] Serve process-slot inference passes from pinned staging batches - #4306
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/rl/4306
Note: Links to docs will display an error until the docs builds have been completed. ⏳ No Failures, 4 PendingAs of commit 9ee51a0 with merge base 5076ae1 ( This comment was automatically generated by Dr. CI and updates every 15 minutes. |
2dff398 to
3f235b5
Compare
These CUDA estimates remain unmeasured. No direct end-to-end gain is expected until #4305 removes the driver bottleneck. |
3f235b5 to
c68b7e3
Compare
|
Measured on the target hardware (64-environment DreamerV3 run on a pixel task, 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. |
c68b7e3 to
cd39d87
Compare
… batches InferenceServer serves ProcessSlotTransport with one batched pass per sweep. Ready slots are claimed without copying (drain_slots) and gathered into a reusable host staging batch with one index_select per leaf (gather_requests); the batch is copied to a persistent policy-device batch with non-blocking transfers (pinned staging on CUDA), padded to the CUDA-graph size by repeating the last request on device, run through the model, and only the declared response keys are copied back to a pinned response batch. One CUDA event per pass waits for that copy instead of the two synchronizing TensorDict.to() calls, and resolve_batch scatters the responses into the slots with one indexed copy per leaf before waking the workers. The interaction code is read from the host batch (no .item() sync) and the CUDA-graph output is consumed by the stream-ordered copy, so the per-pass clone is gone. The per-request path is unchanged for other transports; _run is split into the shared drain loop plus _serve_batch/_serve_slot_batch, and transports opt in through InferenceTransport._batched_slot_io. Custom collate functions keep the per-request path. Adds benchmarks/bench_inference_server.py (requests/s of the process server behind ProcessSlotTransport with 64 clients, eager or CUDA graph) and tests for the batched protocol and pass (CPU) plus a CUDA test for pinned staging, padding, fresh random draws and in-place weight updates. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
cd39d87 to
9ee51a0
Compare
Stack: #4305 → #4306 → #4307 → #4308; depends on #4305.
Batch process-slot inference through reusable pinned buffers, non-blocking transfers, and one CUDA event per pass. Gather/scatter replaces per-request copies; only response keys return to CPU.
Custom collate functions retain their existing path.
Validation: CPU inference suite and metadata regression tests pass. CUDA validation and throughput measurements pending.