Repository navigation
llama, cuda : opt-in AllReduce paths with --allreduce host|p2p - #18
Merged
Merged
Conversation
With peer access llama.cpp left every AllReduce to NCCL. Over a PCIe link NCCL's small reductions have more latency than needed and its kernels hold an SM on each GPU, which slows down the compute of the other ubatch with --split-overlap; a large reduction is bound by the slower link either way. - small reductions (below 512 KiB): a peer-to-peer kernel (allreduce-p2p.cu). Each block writes its slice of the own BF16 contribution into the memory of the other GPU and then its token into that GPU's flag, and polls only its own flag; the data crosses the link once, as posted writes. Two slots alternate; the stream order of the kernels and the growing tokens make that safe without host synchronization. - large reductions: the copy engines copy GPU to GPU (cudaMemcpyPeerAsync) instead of through pinned host memory. Both are on by default with peer access without native peer atomics (PCIe); NVLink keeps NCCL, and so does HIP. GGML_CUDA_AR_P2P_SMALL and GGML_CUDA_AR_CE_P2P override the choice. RTX 4070 + RTX 3060 (PCIe 3.0 x4) with BAR1 P2P, Qwen3.8-27B, -ts 0.625/0.375 -as 1/3, q5_1, -ub 256 --split-overlap, against the same GPUs without peer access: tg32 36.95 -> 37.73 t/s, pp3 97.4 -> 99.6, pp2048 1179 -> 1188, at 16k 35.77 -> 36.48, 77.6 -> 79.2, 1046 -> 1067. Against NCCL with peer access: tg32 34.2 -> 37.7, pp2048 with --split-overlap 865 -> 1188. A small reduction takes 10 us on the 3060 (internal pipeline 17 us, NCCL without P2P 41 us). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- compare the flag with the token in unsigned arithmetic: the signed difference overflowed at token 2^31, and the first GPU to arrive then read a stale slot - peer access over PCIe only with GGML_CUDA_P2P (as in the rest of the backend), not with NCCL_P2P_DISABLE - the copy engines start where the peer-to-peer kernel ends (512 KiB) when GGML_CUDA_AR_NCCL_MIN_BYTES is larger Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The paths of #14, #16 and this PR were chosen by the hardware and switched by environment variables. They are now opt-in with one flag, like the other features of this fork, and the default is upstream's NCCL: - --allreduce host: small reductions through the internal pipeline, large ones through the copy engines, through pinned host memory (#14, #16) - --allreduce p2p: the peer-to-peer kernel and the copy engines from GPU to GPU; host without peer access. The paths enable peer access themselves, GGML_CUDA_P2P is not needed - llama_context_params.allreduce_type, passed to the backends through the new reg proc ggml_backend_comm_set_mode before the meta backends of a context are created - llama-bench -ar, test-llama-archs configs "Meta -ar host" and "Meta -ar p2p -so" - GGML_CUDA_AR_CE, GGML_CUDA_AR_CE_P2P and GGML_CUDA_AR_P2P_SMALL are gone; the two size thresholds stay as tuning variables, GGML_CUDA_ALLREDUCE still overrides - README: the features of this fork as one list (what, benefit, how to enable), and a table upstream vs this fork Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ays-on server changes - test-llama-archs: the reductions of the test models stay below 512 KiB, so the -ar configs never used the copy engines; they now create their contexts with GGML_CUDA_AR_CE_MIN_BYTES=4096 - README: the RAM prompt cache changes of the server are on without a flag Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Adds
--allreduce host|p2pfor-sm tensoron two CUDA GPUs:host: the paths of cuda : reduce small tensors through the internal AllReduce when NCCL has no peer access #14 (small reductions) and cuda : reduce large tensors through the copy engines when NCCL has no peer access #16 (large reductions) through host memory.p2p: new paths with peer access.Without the flag, NCCL does every reduction, as upstream. Before, #14 and #16 were always on and switched by environment variables. After merging, a setup that used them needs
--allreduce host(orp2p), or it falls back to NCCL.The README's fork section is rewritten as one list (what, benefit, how to enable), with an empty table for upstream vs this fork. The server's RAM prompt cache changes are the exception that needs no flag, and the README says so.
Why
On an RTX 4070 + RTX 3060 (PCIe 3.0 x4) with BAR1 P2P, before this PR:
--split-overlap: NCCL's kernels hold an SM on each GPU, which slows down the other ubatch's compute. Prompt processing dropped from 1180 to 865 t/s.Change
--allreduce p2pallreduce-p2p.cu. One kernel per GPU, with 8 blocks.__threadfence_system.f32(bf16(own)) + f32(bf16(peer)). Both GPUs get the same bits.cudaMemcpyPeerAsync, with no pinned memory.p2pfalls back tohostwith a warning.The flag
llama_context_params.allreduce_type(enum llama_allreduce_type) is passed to the backends through a new reg proc,ggml_backend_comm_set_mode. It is called before a context creates its meta backends.--allreducein common, and-arin llama-bench.GGML_CUDA_AR_CE,GGML_CUDA_AR_CE_P2PandGGML_CUDA_AR_P2P_SMALL.GGML_CUDA_AR_NCCL_MIN_BYTESandGGML_CUDA_AR_CE_MIN_BYTES.GGML_CUDA_ALLREDUCEstill overrides the flag.docs/multi-gpu.mddescribes the flag.Results
Qwen3.8-27B UD-Q4_K_S,
-sm tensor -ts 0.625/0.375 -as 1/3, q5_1, native FA,-ub 256 --split-overlap, patched libcuda with BAR1 P2P, t/s:default(NCCL over P2P)hostp2pEarlier run at 16k depth (same configuration),
hostvsp2p: pp2048 1046 vs 1067, pp3 77.6 vs 79.2, tg32 35.77 vs 36.48.In an nsys trace of decode, a small reduction takes 10 µs on the 3060 (median), against 17 µs for the internal pipeline and 41 µs for NCCL without P2P.
Tests
test-llama-archs: the new configs
Meta -ar hostandMeta -ar p2p -sopass on every architecture, with peer access. No failures in the run.Peer access against none:
llama-perplexity --kl-divergence(6 × 2048) gives mean KLD 0 and same top token 100%. The paths use the same arithmetic, so the output is bit-identical.Review, round 2 (reviewer-high): two low findings, both fixed:
Review, round 1 (reviewer-xhigh) found three issues, all fixed:
Also checked in that review:
🤖 Generated with Claude Code