Skip to content

[Bugfix] Engage indexer TP row sharding on total rows, not per-rank rows - #61647

Merged
ZJY0516 merged 7 commits into
vllm-project:mainfrom
zigzagcai:fix/indexer-tp-shard-total-rows
Oct 15, 2026
Merged

ZJY0516 merged 7 commits into
vllm-project:mainfrom
zigzagcai:fix/indexer-tp-shard-total-rows

Conversation

@zigzagcai

@zigzagcai zigzagcai commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

This PR description was written by @ZJY0516.

Overview

Follow-up to #54951, addressing #54951 (comment): gate the sparse-indexer TP row sharding on total scheduled prefill rows instead of per-rank rows, so the 8xH100 TP8 recipe can actually engage it. The floor becomes AttentionConfig.indexer_tp_shard_min_rows (default 65536).

Not a duplicate: no other open PR changes how this floor scales with TP. #60601 lowers the same floor on ROCm only; whichever lands second needs a rebase.

Claims

  • TP8 engages row sharding at --max-num-batched-tokens 65536; before, it needed 131072, which OOMs on 80 GB Hopper.
  • −34.1% mean TTFT on a 1.02M-token prompt at TP8 under an H100-equivalent memory budget.
  • TP4 engagement point unchanged (64K total rows). TP2 moves from 32K to 64K total rows by design.
  • The floor is configurable, e.g. -ac '{"indexer_tp_shard_min_rows": 131072}'.

Validation

Problem reproduced on 8xH200 with an 80 GB-equivalent budget (--gpu-memory-utilization 0.56, TP8, BF16 KV, merged-commit build 3e8e1364):

Config Result
--max-num-batched-tokens 131072 engine init fails: Available KV cache memory: -6.94 GiB
--max-num-batched-tokens 65536 server healthy, but a 70K-token request schedules num_rows=65536 < threshold=131072 on every chunk → 0 engagements

TTFT at the H100 budget (8xH200, --gpu-memory-utilization 0.568 ≈ 81,662 MiB/card vs H100's 81,559 MiB), TP8, --max-num-batched-tokens 65536, --max-model-len 1048576, FP8 KV, FLASH_ATTN_MLA_SPARSE, streaming completions with one request in flight; only the floor differs between arms:

Prompt row-sharded (default) replicated (floor = 2,000,000) Δ mean TTFT
1.02M tok (n=2) 31.57 s 47.92 s −34.1%

The replicated arm was measured with an earlier revision's VLLM_INDEXER_TP_SHARD_MIN_ROWS=2000000; the equivalent now is -ac '{"indexer_tp_shard_min_rows": 2000000}'. The gain grows with context depth (0.48 s saved at 255K vs 16.35 s at 1.02M): per-row indexer cost ramps with causal depth while the per-row exchange cost stays constant.

Tests

  • pytest tests/v1/attention/test_indexer_tp_row_shard.py: 12 passed (TP8 parametrization, total-not-per-rank floor, TP2 32K–64K window stays replicated, floor never below tp_size).
  • End-to-end serve + long-context completions on TP8 at the H100-equivalent budget; engagement verified via NCCL coll logging, outputs sane.

Details

Per rank, the saved replicated indexer work (~ (1 - 1/tp) * rows) and the all_gatherv index traffic (~ (tp - 1)/tp * rows * topk * 4B) both scale with (tp - 1)/tp, so the engagement crossover in total rows is tp-independent to first order. The old per-rank floor grew the total requirement linearly with tp. 65536 is the TP4-calibrated total floor from #54951.

  • TP2 now engages later (64K instead of 32K total rows); the exchange's fixed latency term is largest at small tp.
  • balanced_prefill_row_shard takes the floor as an argument and clamps it to at least tp_size, so every rank always gets at least one row.
  • The floor was calibrated on H200 with NVSwitch; other interconnects were not measured. Startup auto-calibration is a possible follow-up.

Pull Request Checklist
  • I used vLLM's /pr-checklist skill. (Mandatory for agents, optional for humans).

  • AI assistance was used during the creation of this PR.

  • Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.

  • Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.

  • Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.

  • Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.

🤖 Generated with Claude Code

The row-sharding gate introduced in #54951 required
MIN_TP_SHARD_ROWS_PER_RANK * tp_size scheduled prefill rows, so the
total threshold grew linearly with tp_size: TP8 needs 128K rows, i.e.
--max-num-batched-tokens >= 128K, which 80 GB Hopper nodes cannot even
start with (the KV-cache budget goes negative during memory profiling).

Per rank, the saved replicated indexer work (~ (1 - 1/tp) * rows) and
the all_gatherv index traffic (~ (tp - 1)/tp * rows * topk * 4B) scale
identically with tp, so the engagement crossover in TOTAL rows is
tp-independent to first order. Replace the per-rank floor with the
TP4-calibrated total floor of 64K rows, which keeps TP2/TP4 behavior
unchanged and lets TP8 engage with --max-num-batched-tokens 65536.

Also add VLLM_INDEXER_TP_SHARD_MIN_ROWS to override the floor and an
info log on first engagement.

Measured on 8xH200 with an 80 GB-equivalent budget (TP8,
--max-num-batched-tokens 65536, 256K-context requests, vllm bench
serve): mean TTFT 8246 ms -> 7318 ms (-11.3%), zero engagements before
the fix vs. engaged at num_rows=65536 after it.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Zheng Cai <caizheng1993@gmail.com>

@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 pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@mergify mergify Bot added the glm label Oct 14, 2026
Keep the change minimal: the TP-independent total floor already carries
the auto-tune behavior, and no workload has asked for an override yet.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Zheng Cai <caizheng1993@gmail.com>
zigzagcai and others added 2 commits October 15, 2026 12:23
The 64K total floor is calibrated on NVSwitch; on slower interconnects
(e.g. PCIe) the per-row all_gatherv cost is an order of magnitude higher
and the fixed floor would engage a losing path, so deployments need an
escape hatch without a code change.

Drop the info_once engage log: lru_cache keys on (msg, *args), so every
distinct num_rows logs again — noisy over a long-serving run, and not
needed in this PR.

Also pin the TP2 behavior explicitly: 32K-64K total row batches engaged
under the old per-rank floor and now stay replicated; the crossover's
latency term is largest at small tp, so the later engagement is the
right direction, but it is a deliberate change, not an invariant.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@zigzagcai

Copy link
Copy Markdown
Contributor Author

/ci run

@github-actions

Copy link
Copy Markdown

❌ @zigzagcai, A reviewer with write access must run /ci run, approve the PR, or add the ready label first.

ZJY0516 and others added 2 commits October 15, 2026 11:53
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: zjy0516 <riverclouds.zhu@qq.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: zjy0516 <riverclouds.zhu@qq.com>
@ZJY0516 ZJY0516 changed the title [Fix][GLM-5.3-Flash] Engage indexer TP row sharding on total rows, not per-rank rows [Bugfix] Engage indexer TP row sharding on total rows, not per-rank rows Oct 15, 2026
@ZJY0516 ZJY0516 added the ready ONLY add when PR is ready to merge/full CI is needed label Oct 15, 2026
@github-actions

Copy link
Copy Markdown

✅ @zigzagcai, CI is now available for this PR.

  • /ci run starts upstream CI; /amd-ci run starts AMD CI only.
  • Run commands test your branch with every commit currently on its upstream target branch. If it is behind, the bot merges the target branch into it first (pull before pushing again). Append --allow-stale to a run command to test an outdated branch as is, at your own risk.
  • /ci retry retries failed jobs in the CI build for the current PR head. If the current head has no CI build, it starts a new CI build for the current head containing only jobs that failed in the latest earlier CI build for this PR.
  • /amd-ci retry retries failed jobs in AMD CI for the current PR head. Use /amd-ci run when the current head has no AMD CI build.
  • /ci cancel cancels scheduled or running CI builds for this PR branch; /amd-ci cancel does the same for AMD CI only.

@mergify mergify Bot added the bug Something isn't working label Oct 15, 2026

@ZJY0516 ZJY0516 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM now, after some cleanup. BTW, we prefer config instead of env variable

@ZJY0516

ZJY0516 commented Oct 15, 2026

Copy link
Copy Markdown
Member

/ci run

@github-actions

Copy link
Copy Markdown

✅ Triggered Buildkite CI #95122 for commit a03f10b04f9c.

@ZJY0516
ZJY0516 enabled auto-merge (squash) October 15, 2026 12:24
@zigzagcai

Copy link
Copy Markdown
Contributor Author

LGTM now, after some cleanup. BTW, we prefer config instead of env variable

Thanks for the review and changes! Sure, I also think config is betther.

@ZJY0516
ZJY0516 merged commit 24f632c into vllm-project:main Oct 15, 2026
239 checks passed
michael-gpu pushed a commit to practical-inference/vllm-ampere-extended that referenced this pull request Oct 20, 2026
…ows (vllm-project#61647)

Signed-off-by: Zheng Cai <caizheng1993@gmail.com>
Signed-off-by: zjy0516 <riverclouds.zhu@qq.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: zjy0516 <riverclouds.zhu@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working glm ready ONLY add when PR is ready to merge/full CI is needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants