Skip to content

[GG] perf(dcp): merge sparse prefill top-k by row owner#178

Open
voipmonitor wants to merge 3 commits into
local-inference-lab:dev/gilded-gnosisfrom
voipmonitor:perf/gg-dcp-exact-owner-merge-20260725
Open

[GG] perf(dcp): merge sparse prefill top-k by row owner#178
voipmonitor wants to merge 3 commits into
local-inference-lab:dev/gilded-gnosisfrom
voipmonitor:perf/gg-dcp-exact-owner-merge-20260725

Conversation

@voipmonitor

@voipmonitor voipmonitor commented Jul 25, 2026

Copy link
Copy Markdown

Summary

Add an opt-in exact 2D owner merge for sharded sparse-indexer top-k during DCP prefill.

Instead of replicating every rank's candidate rows to every other rank, the path:

  1. routes each contiguous query-row shard to its DCP owner,
  2. performs the exact row top-k over FP32 candidate scores on that owner, and
  3. all-gathers only the final int32 indices to restore TP query order.

VLLM_DCP_TOPK_OWNER_MERGE=0 remains the default. Unsupported shapes and tail rows return to the existing replicated NCCL oracle.

Why

Query split reduces indexer compute, but the existing global top-k merge still replicates all candidate scores and indices. The owner layout preserves sharded scoring and exact FP32 selection while reducing candidate workspace and communication.

Results

GLM-5.2 NVFP4, 8x RTX PRO 6000 Blackwell, TP8/DCP4/MTP0/A16, query split plus full-CKV gather:

Context Existing oracle Owner merge Delta
64k 5,353.7 +/- 4.5 tok/s 5,766.3 +/- 10.6 tok/s +7.71%
400k 4,670.1 tok/s 5,047.8 +/- 8.5 tok/s +8.09%

At the 131k planning profile, KV capacity increased from 2,140,416 to 2,186,496 tokens (+2.15%) because the owner path reserves a smaller candidate-merge workspace.

Correctness and fallback

  • Candidate scores remain FP32; this is not a lossy transport.
  • Query-split TP/DCP rank mapping is checked before dispatch.
  • TP=DCP and TP>DCP layouts are covered.
  • Non-divisible row tails fall back to the established oracle before initializing a new collective.
  • The feature is isolated from replicated-indexer mode.

Validation

  • 22 passed in tests/model_executor/layers/test_sparse_attn_indexer_b12x.py against the exact installed overlay.
  • ruff check and ruff format --check pass for all modified files.
  • TP8/DCP4 E2E measurements completed at 64k and 400k with no request errors.

The separate SparkInfer candidate transport is intentionally not part of this PR. This change uses standard vLLM collectives and is independently useful.

Summary by CodeRabbit

  • New Features

    • Added an opt-in configuration for optimized B12X prefill top-k routing across parallel processing groups.
    • Improved sparse attention routing to merge candidates at their owning shard when supported.
    • Added automatic fallback to the existing routing behavior for unsupported partition layouts.
  • Tests

    • Added coverage for shard splitting, parallel group configurations, fallback handling, and routing selection.

@coderabbitai

coderabbitai Bot commented Jul 25, 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: 2 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: 47fe65e4-8186-4e42-8695-a7a61eafaf60

📥 Commits

Reviewing files that changed from the base of the PR and between 57ae018 and 9a42c71.

📒 Files selected for processing (2)
  • tests/model_executor/layers/test_sparse_attn_indexer_b12x.py
  • vllm/model_executor/layers/sparse_attn_indexer.py
📝 Walkthrough

Walkthrough

Changes

B12X DCP owner merge

Layer / File(s) Summary
Owner-merge configuration and collectives
vllm/envs.py, vllm/model_executor/layers/sparse_attn_indexer.py
Adds the opt-in environment flag, TP-group access, DCP all-to-all buffering, and owner DCP group selection.
Owner-partitioned B12X merge
vllm/model_executor/layers/sparse_attn_indexer.py
Routes candidates to DCP owners, computes local top-k results, gathers results across TP ranks, and falls back when shapes are unsupported.
Prefill routing and validation
vllm/model_executor/layers/sparse_attn_indexer.py, tests/model_executor/layers/test_sparse_attn_indexer_b12x.py
Wires owner merging into prefill execution and tests layouts, TP/DCP parity, tail fallback, and oracle routing.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Prefill as B12X prefill
  participant Merge as _merge_b12x_prefill_dcp_topk
  participant Owner as _merge_b12x_dcp_topk_by_owner
  participant DCP as DCP collectives
  participant TP as TP all-gather
  Prefill->>Merge: merge DCP top-k candidates
  Merge->>Owner: invoke when flag is enabled
  Owner->>DCP: route candidates to owners
  Owner->>TP: gather owner results
  Merge-->>Prefill: return indices and owner-merge status
Loading

Possibly related issues

  • local-inference-lab/rtx6kpro#35 — Covers DCP owner-based top-k merging and related process-group layouts implemented here.

Possibly related PRs

Suggested reviewers: lukealonso, lucifer1004

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: merging sparse prefill top-k by row owner for DCP performance.
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.
✨ 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.

@voipmonitor

Copy link
Copy Markdown
Author

Follow-up fixes the integration contract with partial indexer replication (#179). Owner merge now selects its collective by the indexer KV shard count instead of always using the configured full DCP group, and validates the selected world size. This fixes TP8/DCP8 with a 4-shard partial indexer, which previously failed CUDA-graph warmup with DCP top-k rows must divide the DCP world size. Added a regression test with a larger configured DCP group and a smaller indexer shard group. Validation: 22 passed in test_sparse_attn_indexer_b12x.py; ruff and diff checks pass.

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
tests/model_executor/layers/test_sparse_attn_indexer_b12x.py (2)

899-917: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider covering the fail-closed branches too.

The RuntimeError paths (TP/DCP rank-layout disagreement, invalid trailing shape, non-aliased local rows) are the ones most likely to fire on a misconfigured deployment and currently have no test.

🤖 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 `@tests/model_executor/layers/test_sparse_attn_indexer_b12x.py` around lines
899 - 917, Extend test_b12x_dcp_owner_merge_falls_back_for_tail to cover the
fail-closed RuntimeError branches of _merge_b12x_dcp_topk_by_owner: TP/DCP
rank-layout disagreement, invalid trailing shape, and non-aliased local rows.
Assert each misconfigured input raises RuntimeError while preserving the
existing tail-fallback assertion.

944-948: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

monkeypatch.setattr on the lazy envs module leaves a concrete attribute behind.

vllm.envs resolves flags through module __getattr__; patching then restoring plants a real module attribute that permanently shadows the lazy getter for the rest of the session, so later tests reading VLLM_DCP_TOPK_OWNER_MERGE no longer see env changes. Patching the attribute on the consuming module (indexer_mod) is not possible here since it reads envs.X, so prefer monkeypatch.setenv("VLLM_DCP_TOPK_OWNER_MERGE", ...) plus envs.disable_envs_cache(), or patch indexer_mod.envs with a lightweight stub.

🤖 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 `@tests/model_executor/layers/test_sparse_attn_indexer_b12x.py` around lines
944 - 948, Replace the monkeypatch of indexer_mod.envs.VLLM_DCP_TOPK_OWNER_MERGE
with environment-variable patching via monkeypatch.setenv, using the expected
enabled/disabled value, and call envs.disable_envs_cache() so lazy flag
resolution reflects each test’s environment. Ensure cleanup restores the
environment and cache state without leaving a concrete attribute on the lazy
envs module.
vllm/model_executor/layers/sparse_attn_indexer.py (1)

388-393: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer an explicit injection point over duck-typed getattr(group, "all_to_all_single").

If a real GroupCoordinator ever gains an all_to_all_single attribute (with different semantics/signature), this silently routes production traffic through it instead of the NCCL path. An explicit keyword arg (e.g. all_to_all_fn=None) or a dedicated fake type check makes the test seam unambiguous.

🤖 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 388 - 393,
Replace the duck-typed getattr(group, "all_to_all_single") test seam in the
all-to-all helper with an explicit injected hook, such as an all_to_all_fn
keyword argument defaulting to None. Invoke the injected function only when
provided, otherwise preserve the existing GroupCoordinator NCCL path; do not
infer test behavior from arbitrary group attributes.
🤖 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.

Inline comments:
In `@vllm/model_executor/layers/sparse_attn_indexer.py`:
- Around line 1279-1296: Update the DCP query-split prefill path so merged
scores from _merge_b12x_dcp_topk_by_owner() are copied from owner_values into
the corresponding owner rows of topk_scores_buffer. Include the used_owner_merge
path in the query-split all-gather and write-back logic, keeping gathered
indices and scores synchronized for every query partition.

---

Nitpick comments:
In `@tests/model_executor/layers/test_sparse_attn_indexer_b12x.py`:
- Around line 899-917: Extend test_b12x_dcp_owner_merge_falls_back_for_tail to
cover the fail-closed RuntimeError branches of _merge_b12x_dcp_topk_by_owner:
TP/DCP rank-layout disagreement, invalid trailing shape, and non-aliased local
rows. Assert each misconfigured input raises RuntimeError while preserving the
existing tail-fallback assertion.
- Around line 944-948: Replace the monkeypatch of
indexer_mod.envs.VLLM_DCP_TOPK_OWNER_MERGE with environment-variable patching
via monkeypatch.setenv, using the expected enabled/disabled value, and call
envs.disable_envs_cache() so lazy flag resolution reflects each test’s
environment. Ensure cleanup restores the environment and cache state without
leaving a concrete attribute on the lazy envs module.

In `@vllm/model_executor/layers/sparse_attn_indexer.py`:
- Around line 388-393: Replace the duck-typed getattr(group,
"all_to_all_single") test seam in the all-to-all helper with an explicit
injected hook, such as an all_to_all_fn keyword argument defaulting to None.
Invoke the injected function only when provided, otherwise preserve the existing
GroupCoordinator NCCL path; do not infer test behavior from arbitrary group
attributes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5d8a5093-ad69-4d96-a0e0-f5366328e42a

📥 Commits

Reviewing files that changed from the base of the PR and between 89b4a98 and 57ae018.

📒 Files selected for processing (3)
  • tests/model_executor/layers/test_sparse_attn_indexer_b12x.py
  • vllm/envs.py
  • vllm/model_executor/layers/sparse_attn_indexer.py

Comment thread vllm/model_executor/layers/sparse_attn_indexer.py
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