Skip to content

[GG] perf(indexer): shard sparse prefill queries and halve result traffic#175

Open
voipmonitor wants to merge 2 commits into
local-inference-lab:dev/gilded-gnosisfrom
voipmonitor:perf/gg-query-split-gather-20260724
Open

[GG] perf(indexer): shard sparse prefill queries and halve result traffic#175
voipmonitor wants to merge 2 commits into
local-inference-lab:dev/gilded-gnosisfrom
voipmonitor:perf/gg-query-split-gather-20260724

Conversation

@voipmonitor

@voipmonitor voipmonitor commented Jul 24, 2026

Copy link
Copy Markdown

Summary

  • transpose DCP groups within each independent TP cohort to divide sparse-indexer query rows
  • allow the same exact query sharding at DCP1, where all TP ranks otherwise repeat identical indexer work
  • gather final contiguous int32 top-k indices directly into the caller-owned buffer and stop gathering scores that sparse attention never consumes
  • validate group topology and buffer aliasing, with a safe copied fallback for PyTorch distributed backends that do not expose PyNCCL

The feature remains gated by VLLM_DCP_QUERY_SPLIT. This PR does not globally enable it; the measured launcher policy enables only qualified TP4/TP8 topologies and retains an explicit kill switch.

Why this is exact

Each query-split rank computes a disjoint row slice with the existing sparse top-k kernel, then all-gathers the resulting int32 indices. It does not compress scores, indices, CKV, weights, or activations. A deterministic unique 64k prompt produced the same winning token; baseline-vs-query logprob delta was 7.15e-7 versus 9.54e-7 baseline repeat spread.

Communication impact

For TP8/DCP4, 8192 rows, top-k 2048, and query-split size 2, eliminating the fp32 score collective reduces result traffic per GPU/layer/direction from 64 MiB to 32 MiB. The isolated collective median fell from 2.726 ms to 1.412 ms per active layer and 8k chunk.

E2E results

GLM-5.2, MTP off, exact raw prefill, no concurrent model loading or benchmark traffic:

Topology Context Before After Delta
TP8/DCP1 NVFP4 A16 400k 4,403 5,805 tok/s +31.8%
TP8/DCP1 NVFP4 A16 64k ~5,860 ~6,148 tok/s +4.9%
TP4/DCP1 NF3 hybrid, same GPUs 0-3 64k 4,125 4,226 tok/s +2.4%
TP8/DCP4 NVFP4 A16 64k 5,362.5 5,484.5 tok/s +2.28%

Virtual TP6 has 11 padded heads per rank and is intentionally excluded from auto-enable:

TP6 topology Context Disabled Enabled Delta
DCP1 64k 5,014 4,959 -1.1%
DCP2 64k 3,851 3,830 -0.6%
DCP3 64k / 400k 3,354 / 3,123 2,822 / 2,663 -15.9% / -14.7%
DCP6 64k / 400k 2,306 / 2,238.8 2,288 / 2,236.7 -0.8% / -0.1%

Validation

  • 27 targeted tests passed in the pinned v20 runtime
  • added TP cohort/DCP1 group-layout, invalid-topology, PyNCCL in-place gather, non-PyNCCL alias fallback, and buffer-contract tests
  • Ruff and git diff --check pass
  • TP8/DCP1 64k and 400k E2E
  • TP4/DCP1 64k same-GPU A/B
  • TP6 DCP1/2/3/6 64k and long-context ON/OFF validation
  • TP8/DCP4 two-run E2E validation

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@voipmonitor, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 3 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 246e66ca-13cc-4ca7-8ae7-3b9efbe9db74

📥 Commits

Reviewing files that changed from the base of the PR and between 6cf014d and 2c14a58.

📒 Files selected for processing (4)
  • tests/distributed/test_query_split_groups.py
  • tests/model_executor/layers/test_sparse_attn_indexer_b12x.py
  • vllm/distributed/parallel_state.py
  • vllm/model_executor/layers/sparse_attn_indexer.py
📝 Walkthrough

Walkthrough

Changes

The PR centralizes query-split rank-group construction with validation, adds in-place index all-gather support for B12X sparse prefill, removes score gathering in that path, and adds tests for rank layouts, buffer aliasing, and in-place writes.

Query-split integration

Layer / File(s) Summary
Query-split rank layout
vllm/distributed/parallel_state.py, tests/distributed/test_query_split_groups.py
Adds validated DCP-sized rank grouping, preserves TP ranks for query-split construction, and tests valid and invalid configurations.
In-place query-split index gathering
vllm/model_executor/layers/sparse_attn_indexer.py, tests/model_executor/layers/test_sparse_attn_indexer_b12x.py
Adds validated gathering into a caller-owned index buffer and tests in-place writes, unchanged scores, and aliasing requirements.
B12X prefill integration
vllm/model_executor/layers/sparse_attn_indexer.py
Uses the new index gather helper, resolves query-split groups directly, and no longer gathers scores during this stage.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant B12XPrefill
  participant QuerySplitGroup
  participant GatheredIndices
  B12XPrefill->>QuerySplitGroup: resolve query-split group
  B12XPrefill->>GatheredIndices: gather top-k indices in place
  QuerySplitGroup-->>GatheredIndices: provide rank-local slices
  GatheredIndices-->>B12XPrefill: restored gathered indices
Loading

Possibly related PRs

Suggested reviewers: lukealonso, yewentao256

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main optimization: sharding sparse prefill queries and reducing communication traffic.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (2)
vllm/model_executor/layers/sparse_attn_indexer.py (1)

399-402: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Cover the non-PyNCCL aliasing path.

The added test exercises only pynccl_comm.all_gather; the fallback passes an aliased rank-local view to torch.distributed.all_gather_into_tensor. Add backend-level coverage or verify the deployed PyTorch/NCCL combination supports this exact in-place layout before relying on it. NCCL documents the rank-local condition as sendbuff == recvbuff + rank * sendcount, while PyTorch’s API documentation specifies sizing but not this aliasing guarantee. (github.com)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vllm/model_executor/layers/sparse_attn_indexer.py` around lines 399 - 402,
Update _dcp_all_gather_first_dim_into to cover or validate the aliased
rank-local send-buffer path used by torch.distributed.all_gather_into_tensor,
not only pynccl_comm.all_gather. Add backend-level coverage for the exact
in-place layout, or establish an explicit PyTorch/NCCL capability check and
provide a safe non-aliased fallback when unsupported.
vllm/distributed/parallel_state.py (1)

1450-1453: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document both new helpers with Google-style sections.

Both helpers accept arguments and raise validation errors, but their docstrings contain only a summary.

  • vllm/distributed/parallel_state.py#L1450-L1453: add Args:, Returns:, and Raises: sections describing the TP cohorts, DCP size, output groups, and ValueError.
  • vllm/model_executor/layers/sparse_attn_indexer.py#L375-L380: add Args:, Returns:, and Raises: sections describing the group, buffers, and validation failures.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vllm/distributed/parallel_state.py` around lines 1450 - 1453, Document both
helpers with Google-style Args, Returns, and Raises sections: in
vllm/distributed/parallel_state.py lines 1450-1453, update
_get_query_split_group_ranks to describe TP cohorts, dcp_size, transposed output
groups, and ValueError validation; in
vllm/model_executor/layers/sparse_attn_indexer.py lines 375-380, update the
corresponding helper’s docstring to describe its group and buffers, return
value, and validation failures.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@vllm/distributed/parallel_state.py`:
- Around line 1450-1453: Document both helpers with Google-style Args, Returns,
and Raises sections: in vllm/distributed/parallel_state.py lines 1450-1453,
update _get_query_split_group_ranks to describe TP cohorts, dcp_size, transposed
output groups, and ValueError validation; in
vllm/model_executor/layers/sparse_attn_indexer.py lines 375-380, update the
corresponding helper’s docstring to describe its group and buffers, return
value, and validation failures.

In `@vllm/model_executor/layers/sparse_attn_indexer.py`:
- Around line 399-402: Update _dcp_all_gather_first_dim_into to cover or
validate the aliased rank-local send-buffer path used by
torch.distributed.all_gather_into_tensor, not only pynccl_comm.all_gather. Add
backend-level coverage for the exact in-place layout, or establish an explicit
PyTorch/NCCL capability check and provide a safe non-aliased fallback when
unsupported.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0d9320bf-f356-453b-9328-050d15b6c3fc

📥 Commits

Reviewing files that changed from the base of the PR and between 4a4299c and 6cf014d.

📒 Files selected for processing (4)
  • tests/distributed/test_query_split_groups.py
  • tests/model_executor/layers/test_sparse_attn_indexer_b12x.py
  • vllm/distributed/parallel_state.py
  • vllm/model_executor/layers/sparse_attn_indexer.py

@voipmonitor
voipmonitor force-pushed the perf/gg-query-split-gather-20260724 branch from 6cf014d to f8c0cb4 Compare July 24, 2026 22:35
@voipmonitor
voipmonitor force-pushed the perf/gg-query-split-gather-20260724 branch from f8c0cb4 to 599d3f6 Compare July 24, 2026 22:37
@voipmonitor voipmonitor changed the title [GG] perf(dcp): halve query-split result traffic [GG] perf(indexer): shard sparse prefill queries and halve result traffic Jul 24, 2026
@voipmonitor

Copy link
Copy Markdown
Author

Addressed the review findings while rebasing onto current dev/gilded-gnosis:

  • the PyNCCL path keeps the validated zero-copy NCCL alias contract
  • the generic torch.distributed fallback now detects overlapping send/receive storage and clones only the send slice before all_gather_into_tensor
  • added a forced fallback regression test and Google-style helper contracts
  • expanded the same coherent query-split path to DCP1 after TP8/TP4 E2E qualification; TP6 remains launcher-disabled

Validation: 27/27 targeted tests, Ruff, and git diff --check.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant