perf: reuse HybridEP routing allgather buffer - #716
Draft
akoumpa wants to merge 3 commits into
Draft
Conversation
Signed-off-by: Alexandros Koumparoulis <akoumparouli@nvidia.com>
Signed-off-by: Alexandros Koumparoulis <akoumparouli@nvidia.com>
Signed-off-by: Alexandros Koumparoulis <akoumparouli@nvidia.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.
Summary
Reuse HybridEP's preallocated allgather output buffer for the NCCL/inter-node routing-map allgather instead of allocating a temporary CUDA tensor during every dispatch.
The routing map is consumed by metadata preprocessing on the same stream before the next dispatch can reuse the buffer, so its lifetime does not overlap the following collective.
Memory impact
The removed temporary allocation contains the globally gathered routing payload on every rank.
For sparse Boolean routing, the saved allocation per rank is:
For dense
int16routing, it is:For the stress configuration used during validation (
8192tokens/rank,8ranks,256experts, and top-k36), this avoids:Implementation
CustomAllgather::get_output_buffer()as the NCCL allgather output tensor.bool/int16dtype, routing shape, and byte views used for NCCL.Testing
Validation was performed on H100 GPUs using a multi-node DOCA/RDMA build in both of these topologies:
Output and gradient regression
Added
tests/test_allgather_grad_validation.py, which compares the reused-buffer path with the existing allgather behavior.The test covers the Cartesian product of:
This produces 12 cases per topology. Each case validates:
Nonebehavior.All 12 cases passed on both the single-node and two-node topologies.
Full HybridEP reference validation
Ran
tests/test_hybrid_ep.pywith 512 tokens/rank, eight local experts, top-k 8, hidden dimension 1024, and padding multiple 32.The following passed for both BF16 and FP8 on both topologies:
The API-level and kernel-level benchmark loops also completed successfully.
CUDA graph and nonblocking validation
Ran
tests/test_graphed_hybrid_ep.pyacross:All combinations passed on every rank in both topologies.
Harry Zhou's standalone allgather stress test
Thanks to Harry Zhou for providing
test_allgather.py, which was used as an additional correctness and stress test.It was run in both single-node and two-node configurations with its original stress dimensions:
For both dense-index and sparse-Boolean routing:
Thanks again to Harry for the focused test coverage and stress configuration.
Static checks
The new regression test also passed Ruff linting, Ruff formatting, Python bytecode compilation, and repository pre-commit checks.