Skip to content

perf: add push-based allreduce for small tensor reductions - #44891

Open
alexm-redhat wants to merge 9 commits into
mainfrom
perf/push-allreduce-2buffer
Open

alexm-redhat wants to merge 9 commits into
mainfrom
perf/push-allreduce-2buffer

Conversation

@alexm-redhat

Copy link
Copy Markdown
Collaborator

Summary

This PR adds a push-based 2-buffer allreduce protocol to vLLM, targeting small-message reductions during decode (e.g., the per-layer attention and MoE allreduces in DeepSeek-V4 models). The existing barrier-based CustomAllreduce uses two explicit cross-GPU NVLink barrier round-trips per call, which dominate latency for small tensors. The push protocol eliminates these barriers entirely by having each rank push its data to all remote GPUs via NVLink volatile stores and then polling locally for arrival using a positive-zero sentinel mechanism with double-buffered epoch alternation.

The new PushAllReduce communicator is inserted into the CudaCommunicator dispatch chain above the existing CustomAllreduce for messages below a dynamic size threshold (~720 KB at TP=8 on B200). Messages above this threshold continue to use the barrier-based path. No existing CustomAllreduce code is modified. The implementation includes a consolidated CUDA kernel header vendored from SGLang's proven push kernel with minimal macro substitutions (namespace, C++17 compatibility, AOT compilation guards), a C++ host-side manager class following vLLM patterns, torch custom op bindings, and a Python communicator wrapper with CUDA graph support.

The kernel uses all available SMs (vs 2 CTAs in the barrier-based approach), supports PDL (griddepcontrol) overlap on sm_90+ architectures, and avoids the cudaMemcpy to IPC staging buffer required by the barrier-based path in eager mode. CUDA graph safety is ensured by placing the epoch counter in device memory (read live during replay) with a fixed grid size equal to the SM count.

Performance Results

Configuration Metric Baseline Patched Delta Change
DeepSeek-V4-Pro (8xB200, TP=8) Throughput (tok/s) 82.301 84.060 +1.759 +2.14%
DeepSeek-V4-Pro (8xB200, TP=8) TPOT (ms/tok) 12.152 11.897 -0.255 -2.09%
DeepSeek-V4-Flash (2xB200, TP=2) Throughput (tok/s) 127.035 130.905 +3.870 +3.05%
DeepSeek-V4-Flash (2xB200, TP=2) TPOT (ms/tok) 7.873 7.640 -0.233 -2.96%

Workload: decode, BS=1, ISL=4, OSL=33024, KV cache FP8. Baseline = same patched code with push allreduce disabled via env var (falls back to barrier-based CustomAllreduce).

Per-call improvement on V4-Pro (122 allreduce calls per forward pass across 61 layers): ~2.09 us/call.

Correctness (lm_eval)

Configuration Metric Baseline Patched Delta Status
DeepSeek-V4-Pro (8xB200, TP=8) flexible-extract exact_match 0.9515 0.9530 +0.0015 PASS
DeepSeek-V4-Pro (8xB200, TP=8) strict-match exact_match 0.9515 0.9538 +0.0023 PASS
DeepSeek-V4-Flash (2xB200, TP=2) flexible-extract exact_match 0.9598 0.9530 -0.0068 PASS
DeepSeek-V4-Flash (2xB200, TP=2) strict-match exact_match 0.9606 0.9530 -0.0076 PASS

Benchmark: gsm8k 5-shot (1319 prompts). All deltas are within 1 standard error (~0.006) and statistically indistinguishable (z-scores < 1.96). The sign reversal between configurations confirms random variance, not a systematic shift.

Feature Toggle

Item Value
Environment variable VLLM_DISABLE_PUSH_ALLREDUCE
Disable command VLLM_DISABLE_PUSH_ALLREDUCE=1
Startup log (enabled) AllReduce push-based 2-buffer protocol is ENABLED
Startup log (disabled) AllReduce push-based 2-buffer protocol is DISABLED (env override)

When disabled, PushAllReduce.__init__ returns immediately without allocating any GPU resources. should_use() returns False for all inputs, and CudaCommunicator falls through to the barrier-based CustomAllreduce.

Test Coverage

24 tests included in the patch, all passing on 2x NVIDIA B200:

  • Unit tests (16): build verification, initialization/IPC exchange, should_use() predicate logic, bit-exact integer correctness vs NCCL, float correctness, positive-zero sentinel handling, 1000-call epoch alternation, thread count selection, threshold boundary, out-of-place semantics, dtype coverage (fp16/bf16/fp32), multi-layer simulation (122 ARs x 3 steps), lifecycle/cleanup, warmup path, asymmetric rank data, identical-values edge case
  • Integration tests (3): dispatch priority routing (small->push, large->fallback), coexistence with existing allreduce backends, interleaved push AR + NCCL operations
  • CUDA graph test (1): graph capture + 10 replays with varying data, epoch counter correctness
  • E2E test (1): transformer block simulation (61 blocks x 2 ARs x 2 decode steps)
  • Feature toggle tests (3): enabled default, disabled via env var, non-"1" values do not disable

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@mergify

mergify Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @alexm-redhat.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

Comment thread tests/distributed/_test_push_ar_worker.py Fixed
Comment thread tests/distributed/test_push_all_reduce.py Fixed
Comment thread csrc/push_all_reduce.cuh Outdated

// Allocate storage
storage_bytes_ = push_signal_bytes() + push_buffer_total_bytes();
cudaMalloc(&storage_, storage_bytes_);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: LOW

All CUDA API calls (cudaMalloc, cudaMemset, cudaIpcGetMemHandle, cudaIpcOpenMemHandle) lack error checking. The existing custom_all_reduce.cu wraps these with AT_CUDA_CHECK(). If cudaMalloc fails, storage_ remains null, and the subsequent cudaMemset and all kernel operations write through an invalid pointer, causing undefined behavior.
Helpful? Add 👍 / 👎

💡 Fix Suggestion

Suggestion: Wrap all CUDA API calls with AT_CUDA_CHECK() to match the existing pattern used in custom_all_reduce.cu. This applies to cudaMalloc, cudaMemset, cudaGetDevice, cudaDeviceGetAttribute, cudaIpcGetMemHandle, cudaIpcOpenMemHandle, and other CUDA calls throughout this file. You will also need to add #include <ATen/cuda/Exceptions.h> at the top of the file to make AT_CUDA_CHECK available. At the immediate location (lines 44-48), change cudaMalloc(...) to AT_CUDA_CHECK(cudaMalloc(...)) and cudaMemset(...) to AT_CUDA_CHECK(cudaMemset(...)). Apply the same wrapping to all other unchecked CUDA calls in the file (lines 37, 39-40, 56, 60, 67, 78, and the destructor calls).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — added CUDACHECK wrapping for all CUDA API calls.

Comment thread csrc/push_all_reduce.cuh Outdated
// Verify input fits in push buffer
const int64_t input_bytes =
static_cast<int64_t>(sizeof(T)) * num_elements;
assert(input_bytes <= push_buffer_bytes_);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: LOW

This buffer-overflow guard uses assert(), which is compiled out under the default RelWithDebInfo build (-DNDEBUG). If all_reduce() is called with an input exceeding push_buffer_bytes_ (the Python all_reduce method has no independent size check), the kernel performs volatile NVLink stores past the allocated push buffer into adjacent GPU memory on all peers.
Helpful? Add 👍 / 👎

💡 Fix Suggestion

Suggestion: Replace the assert() with a runtime check that is not removed by -DNDEBUG. Since this .cuh header does not include Torch headers, the simplest fix is to replace the assert with an explicit if check that throws a std::runtime_error. You will also need to add #include <stdexcept> to the existing includes at the top of the file (or alternatively, include <torch/all.h> and use TORCH_CHECK). Replace line 99:

assert(input_bytes <= push_buffer_bytes_);

with:

if (input_bytes > push_buffer_bytes_) {
  throw std::runtime_error(
      "push_all_reduce: input (" + std::to_string(input_bytes) +
      " bytes) exceeds push buffer capacity (" +
      std::to_string(push_buffer_bytes_) + " bytes)");
}

Also add #include <stdexcept> near line 14 alongside the other standard library includes.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — replaced assert with a runtime buffer overflow guard that is not compiled out under NDEBUG.

Comment thread csrc/push_all_reduce.cuh Outdated
if (i == rank_) {
peer_storage_[i] = storage_;
} else {
cudaIpcOpenMemHandle(&peer_storage_[i], peer_handles[i],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Severity: LOW

The cudaIpcOpenMemHandle return value is unchecked. If it fails (e.g. invalid/corrupted IPC handle), peer_storage_[i] is left as null/undefined. The kernel then performs NVLink volatile stores to these invalid addresses via push_impl, corrupting arbitrary remote GPU memory.
Helpful? Add 👍 / 👎

💡 Fix Suggestion

Suggestion: Wrap the cudaIpcOpenMemHandle call with a CUDA error-checking macro to detect and handle failures. The repo already defines a CUDACHECK macro in custom_all_reduce.cuh. Either include that header or define an equivalent macro in push_all_reduce.cuh, then wrap the call:

CUDACHECK(cudaIpcOpenMemHandle(&peer_storage_[i], peer_handles[i],
                                cudaIpcMemLazyEnablePeerAccess));

Note: the same error-checking gap applies to other unchecked CUDA calls in this file (cudaIpcGetMemHandle at line 67, cudaMalloc/cudaMemset in the constructor, cudaFree in the destructor). Consider wrapping all of them consistently.

⚠️ Experimental Feature: This code suggestion is automatically generated. Please review carefully.

Suggested change
cudaIpcOpenMemHandle(&peer_storage_[i], peer_handles[i],
CUDACHECK(cudaIpcOpenMemHandle(&peer_storage_[i], peer_handles[i],
cudaIpcMemLazyEnablePeerAccess));

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — added CUDACHECK wrapping for cudaIpcOpenMemHandle and all other unchecked CUDA calls.

@alexm-redhat

Copy link
Copy Markdown
Collaborator Author

@ilmarkov would be good to have a quick sanity check

@ilmarkov ilmarkov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR!
In this review I focused on the integration of the kernel postponing the review of the copy-pasted kernel (assume it works fine in Sglang).

Some comments:

  • I would suggest is to add the kernel to benchmark_device_communicators.py to compare to the other implementations and possibly tune the thresholds on other architectures.
  • VLLM_DISABLE_PUSH_ALLREDUCE not registered in envs.py
  • Update with the latest main and add the method to _log_all_reduce_backend_selection

@@ -81,6 +80,7 @@ def __init__(
register_nccl_symmetric_ops(self.pynccl_comm)

self.ca_comm: CustomAllreduce | None = None
self.push_ar_comm = None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, type annotation to be consistent with other communicators.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — added type annotation for consistency with other communicators.


# Push threshold map: world_size -> buffer_bytes
# From SGLang's tuned thresholds for sm100 (B200)
PUSH_THRESHOLD_SM100 = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it is applied unconditionally to all archs

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — added architecture-specific threshold selection.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing cleanup

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — added cleanup.

@tlrmchlsmth

Copy link
Copy Markdown
Member

Workload: decode, BS=1, ISL=4, OSL=33024, KV cache FP8. Baseline = same patched code with push allreduce disabled via env var (falls back to barrier-based CustomAllreduce).

This is a pretty strange workload - what is the performance in a more realistic scenario?

@alexm-redhat
alexm-redhat force-pushed the perf/push-allreduce-2buffer branch 2 times, most recently from 6d32045 to 7e7e30c Compare June 15, 2026 21:59
@alexm-redhat

Copy link
Copy Markdown
Collaborator Author

The test was done for a KV cache long workload which Roberto said is more typical for DeepSeek V4. Will test more use-cases.

@alexm-redhat

alexm-redhat commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator Author

@ilmarkov Thank you for the review!

  1. Add kernel to benchmark_device_communicators.py — Done. Added PushAllReduce initialization and benchmark entry following the same pattern as the other communicators (with should_use gate and capture() context for CUDA graph benchmarking).

  2. VLLM_DISABLE_PUSH_ALLREDUCE not registered in envs.py — Done (addressed in earlier commit).

  3. Update with latest main and add to _log_all_reduce_backend_selection — Done. Rebased on latest main and added PUSH_AR to both all_potential_ar_backends and the enabled-backends check in _log_all_reduce_backend_selection, in the correct dispatch order (between FLASHINFER and CUSTOM).

@mergify mergify Bot added the performance Performance-related issues label Jun 15, 2026
alexm-redhat and others added 8 commits June 15, 2026 18:09
Port SGLang's push-based 2-buffer allreduce protocol into vLLM as a new
communicator backend for small-message reductions. The push protocol
eliminates the two explicit cross-GPU NVLink barrier round-trips used by
the existing barrier-based CustomAllreduce, replacing them with a
sentinel-based data arrival detection mechanism and double-buffered epoch
alternation.

Key advantages over the barrier-based approach:
- Zero barriers: data arrival IS the synchronization (positive-zero sentinel)
- Single NVLink round-trip instead of two barrier exchanges + remote reads
- All SMs active (SM_count CTAs vs 2 CTAs) for higher NVLink bandwidth
- No cudaMemcpy to IPC staging buffer in eager mode
- PDL (griddepcontrol) support for kernel overlap on sm_90+

The new PushAllReduce is inserted in the CudaCommunicator dispatch chain
above the existing CustomAllreduce for messages below a size threshold
(~720 KB at TP=8). Larger messages continue to use the barrier-based
path. The existing CustomAllreduce code is not modified.

Measured results on DeepSeek-V4-Pro (61 layers, TP=8, 8x NVIDIA B200,
BS=1, decode with ISL=4, OSL=33024):
- Throughput: +2.14% (84.06 vs 82.30 tokens/s)
- TPOT: -2.09% (11.90 vs 12.15 ms/token)

Correctness verified via lm_eval gsm8k 5-shot with no regression
(exact_match delta within statistical noise).

The feature can be disabled at runtime via VLLM_DISABLE_PUSH_ALLREDUCE=1
to fall back to the barrier-based path.

Signed-off-by: Alexander Matveev <amatveev@redhat.com>
Signed-off-by: Alexander Matveev <alexm-redhat@dgx-b200-02.mgmt.accl-001.lab.rdu2.dc.redhat.com>
…uard

- Add PUSH_AR_CUDACHECK macro wrapping all CUDA API calls (cudaGetDevice,
  cudaDeviceGetAttribute, cudaMalloc, cudaMemset, cudaIpcGetMemHandle,
  cudaIpcOpenMemHandle) to match the CUDACHECK pattern in custom_all_reduce.cuh
- Replace assert(input_bytes <= push_buffer_bytes_) with a runtime
  std::runtime_error check that is not compiled out under -DNDEBUG
- Add #include <stdexcept> and #include <string> for the runtime check

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Alexander Matveev <alexm-redhat@dgx-b200-02.mgmt.accl-001.lab.rdu2.dc.redhat.com>
Fix CodeQL security warning by binding test helper sockets to
"localhost" instead of "" (all interfaces). These sockets are only
used for finding a free port for torch distributed init in tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Alexander Matveev <alexm-redhat@dgx-b200-02.mgmt.accl-001.lab.rdu2.dc.redhat.com>
- Add PushAllReduce | None type annotation on push_ar_comm to be
  consistent with other communicator fields (ca_comm, qr_comm, etc.)
- Add push_ar_comm.close() + None assignment in destroy() method
  to match the cleanup pattern for other communicators
- Add lazy import of PushAllReduce alongside other communicator imports

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Alexander Matveev <alexm-redhat@dgx-b200-02.mgmt.accl-001.lab.rdu2.dc.redhat.com>
The push threshold map was labeled as sm100-specific but applied
unconditionally to all architectures. Now:
- PUSH_THRESHOLD_SM100 is only used on Blackwell (compute capability 10.x)
- PUSH_THRESHOLD_DEFAULT provides conservative 512 KB thresholds for
  architectures without tuned values
- _THRESHOLD_BY_ARCH maps GPU major compute capability to threshold tables
- A log message is emitted when falling back to conservative defaults

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Alexander Matveev <alexm-redhat@dgx-b200-02.mgmt.accl-001.lab.rdu2.dc.redhat.com>
Register the push allreduce feature toggle env var in the central
envs.py registry so it is validated on startup and follows the
standard vllm env var pattern. Default is False (push allreduce
enabled); set to 1 to disable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Alexander Matveev <alexm-redhat@dgx-b200-02.mgmt.accl-001.lab.rdu2.dc.redhat.com>
Replace direct os.environ.get(_DISABLE_ENV_VAR) == "1" check with
envs.VLLM_DISABLE_PUSH_ALLREDUCE to use the centrally registered
env var from envs.py, which provides validation and caching.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Alexander Matveev <alexm-redhat@dgx-b200-02.mgmt.accl-001.lab.rdu2.dc.redhat.com>
- Add PushAllReduce to benchmark_device_communicators.py for
  comparing against other allreduce implementations
- Add PUSH_AR to _log_all_reduce_backend_selection in
  cuda_communicator.py for visibility in dispatch logging

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Alexander Matveev <alexm-redhat@dgx-b200-02.mgmt.accl-001.lab.rdu2.dc.redhat.com>
@alexm-redhat
alexm-redhat force-pushed the perf/push-allreduce-2buffer branch from b833264 to fd44100 Compare June 15, 2026 22:09
- Apply ruff, clang-format formatting fixes
- Replace torch.cuda.set_device/device_count/synchronize with
  torch.accelerator equivalents per project convention

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Alexander Matveev <alexm-redhat@dgx-b200-02.mgmt.accl-001.lab.rdu2.dc.redhat.com>

Signed-off-by:  <>
@mergify mergify Bot removed the needs-rebase label Jun 15, 2026
@ilmarkov

Copy link
Copy Markdown
Contributor

@alexm-redhat Looks good, thanks!

Could you please add the allreduce benchmark results to the description to verify that the hardcoded constants actually make sense?
Also, I agree with @tlrmchlsmth , we need to verify that new kernel doesn't add regression in other scenarios.

@alexm-redhat

Copy link
Copy Markdown
Collaborator Author

@ilmarkov ok will do, yeah in process of running more tests

@mergify

mergify Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @alexm-redhat.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Jun 19, 2026
@alexm-redhat

alexm-redhat commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator Author

@ilmarkov @tlrmchlsmth here is a summary of extensive nightly benchmarks. Everything seems to be working, also verified thresholds.

Push AllReduce Benchmark Results — Complete Summary

Hardware: 8x NVIDIA B200 (183 GiB each), NVLink
Benchmark: vllm bench throughput, async-engine, async-scheduling, fp8 kv-cache
Models: DeepSeek-V4-Flash (TP=4, hidden=4096), DeepSeek-V4-Pro (TP=8, hidden=7168)

Push AR dispatches when allreduce message fits in buffer:
msg_size = num_decode_tokens × hidden_size × 2 bytes (BF16)

  • Flash (TP=4): threshold = 2 MB → push AR for ≤ 256 decode tokens
  • Pro (TP=8): threshold = 720 KB → push AR for ≤ 51 decode tokens

1. Batch=1 across ISL/OSL configurations

DeepSeek V4 Flash (TP=4, 4x B200)

ISL/OSL Disabled (tok/s) Enabled (tok/s) Speedup
1024/1024 307.5 315.4 +2.6%
8192/1024 1,349.2 1,379.5 +2.2%
1024/256 726.7 744.1 +2.4%
4/128 142.0 145.4 +2.4%

DeepSeek V4 Pro (TP=8, 8x B200)

ISL/OSL Disabled (tok/s) Enabled (tok/s) Speedup
1024/1024 189.4 193.8 +2.3%
8192/1024 817.3 834.5 +2.1%
1024/256 451.4 461.2 +2.2%
4/128 89.2 91.0 +2.0%

2. Batch size scaling (ISL/OSL=1024/1024)

DeepSeek V4 Flash (TP=4, 4x B200) — threshold = 2 MB

Batch Disabled (tok/s) Enabled (tok/s) Speedup Push AR?
1 307.5 315.4 +2.6% yes
16 3,414.7 3,482.4 +2.0% yes
32 5,178.0 5,891.8 +13.8% yes
48 6,276.5 7,362.3 +17.3% yes
64 9,016.1 9,607.2 +6.6% yes (verified)
128 11,210.0 15,006.2 +33.9% yes
256 20,742.8 21,374.9 +3.0% yes (boundary)
512 27,832.8 27,879.2 +0.2% no (fallback)
1024 27,967.8 27,968.1 +0.0% no (fallback)

DeepSeek V4 Pro (TP=8, 8x B200) — threshold = 720 KB

Batch Disabled (tok/s) Enabled (tok/s) Speedup Push AR?
1 189.4 193.8 +2.3% yes
16 2,089.6 2,106.5 +0.8% yes (verified)
32 3,146.8 3,416.6 +8.6% yes
48 3,562.3 4,043.9 +13.5% yes
64 4,938.8 4,943.0 +0.1% no (fallback)
128 7,779.5 7,784.5 +0.1% no (fallback)
256 10,942.9 10,873.2 -0.6% no (fallback, noise)
512 12,794.0 12,790.9 -0.0% no (fallback)
1024 12,787.0 12,868.8 +0.6% no (fallback, noise)

Key Findings

  1. No regressions in any configuration. All negative deltas are within +/-0.6% run-to-run noise.

  2. Batch=1 latency is not harmed: consistent +2% improvement across all ISL/OSL configs on both models.

  3. Push AR provides clear gains within its threshold range:

    • Flash peaks at b128 (+33.9%) with gains across b1–b256.
    • Pro peaks at b48 (+13.5%) with gains at b1–b48.
  4. Above the threshold, push AR falls back to the existing custom allreduce with zero overhead.

  5. Pro's smaller effective range (b1–b48) vs Flash (b1–b256) is due to its larger hidden_size (7168 vs 4096) and higher TP (8 vs 4), which together produce larger allreduce messages
    that exceed the 720 KB buffer sooner.

  6. Dips at Flash b64 (+6.6%) and Pro b16 (+0.8%) were verified with re-runs and are real. They reflect the non-linear interplay between allreduce fraction and the scheduler's
    prefill/decode mix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants