Repository navigation
fix(group): ⚡️ run each rank on a non-blocking stream - #75
Merged
Merged
Conversation
The ranks of a DeviceGroup ran on CuPy's legacy null stream, where a peer copy into one GPU serializes with the copy in the other direction. Every allgather over PCIe got half the bandwidth: 19.5/11.0/6.6 GB/s per receiver at 2/4/8 GPUs, against 34.8/15.3/11.3 on non-blocking streams. Each rank now runs on a non-blocking stream of its device, one per device and reused across calls so that CuPy's pool keeps reusing its cached blocks. The stream waits for the caller's current stream on entry and is synchronized on exit. On 8x RTX PRO 6000 (PCIe, complex64, D_M = 4000, chi = 2000) the 8-GPU sweep drops from 169.3 s to 145.5 s, 63% to 73% parallel efficiency, with unchanged outputs. Assisted-by: Claude Code:claude-opus-5-5
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix(group): ⚡️ run each rank on a non-blocking stream
🤖 AI text below 🤖
What
DeviceGroup.runnow runs each rank on a non-blocking CUDA stream of its device(
utils._backend.use_stream) instead of CuPy's legacy null stream.only on the stream that allocated it, so a new stream per call would strand the
previous call's cached blocks.
are still being computed are ordered correctly. On normal exit it is
synchronized, so the returned cores are ready on any stream.
use_streamis a no-op there.Why
On the legacy null stream, a peer copy into GPU A serializes with the copy from A
into B. Every allgather in the sweep (
S_jand the core uploads) therefore gothalf the PCIe bandwidth. The scaling runs on 8x RTX PRO 6000 (PCIe only) traced
this, see
benches/large/nebius/summary.mdonbench/nebius-rtx:DeviceGroup.allgatheralone, per receiverResults
8x RTX PRO 6000 Blackwell, PCIe 5.0, no NVLink, complex64, the same stacks as the
bench branch. Efficiency is against the 1-GPU time from that branch's step 4 (847 s
and 20.3 s).
The outputs are unchanged. At D_M = 1000 the QR distance of each GPU count to the
1-GPU output is the same as before to every printed digit (8.45e-5, 7.79e-5,
7.84e-5). The before and after times were measured in separate runs, since the
library change cannot run side by side with the old code.
The remaining gap to the bandwidth probe at 4 and 8 GPUs comes from the
collective's events and barriers. It is not addressed here.
Tests
test_host_use_stream_is_a_no_op.test_group_runs_on_a_non_blocking_stream: not the null stream, the same streamacross runs, and work queued earlier on the null stream is seen.
test_two_gpus_run_on_their_own_streams.uv run prek run --all-filesis clean.uv run pytest -m "not slow"passes(396 tests), including
tests/test_gpu_backend.pyon 8 GPUs.🤖 Generated with Claude Code