Skip to content

[BugFix][MRV2] Align PCP slot buffer dtype with Ascend block tables - #16762

Draft
recky-c wants to merge 2 commits into
vllm-project:mainfrom
recky-c:fix/pcp-slot-dtype-minimal
Draft

recky-c wants to merge 2 commits into
vllm-project:mainfrom
recky-c:fix/pcp-slot-dtype-minimal

Conversation

@recky-c

@recky-c recky-c commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

What this PR does / why we need it?

MRV2 PCP supplies its own output buffers to compute_slot_mappings, bypassing the normal Ascend int32 slot buffer. The upstream PCP buffers are int64, while the C8 store_kv_block_metadata kernel reads slots as int32, which can generate incorrect cache-write metadata on PD producers.

Initialize the Ascend PCP global and gathered slot buffers with block_tables.slot_mappings.dtype, and align the padding scalar. Allocation happens once before graph capture; normal computation, dummy inputs and graph padding continue to reuse the persistent buffers. No upstream vLLM, attention call sites or native operators are changed.

Related: #16664 already fixes the dtype issue at the operator call site. This draft proposes an alternative fix at the PCP buffer source for review, rather than an independent issue. It does not include that PR's separate PCP+DCP SFA slot-length fix. Maintainers should coordinate the overlapping dtype changes.

Does this PR introduce any user-facing change?

Intended to fix incorrect C8 cache writes caused by PCP slot dtype mismatches. No configuration changes. This follows the existing Ascend block-table dtype and capacity assumptions; it does not add range checks or claim all slot paths in the repository use int32.

How was this patch tested?

  • Python AST parsing and git diff --check passed.
  • Added a regression test for dtype alignment, gathered slot values and masking, dummy padding, and persistent buffer address reuse, parameterized over int32 and int64 block-table buffers.
  • Intended test command: pytest -q tests/ut/worker/test_pcp_manager_v2.py -k slot_buffers_match.
  • Runtime tests could not run in the local Windows environment because PyTorch and pytest are unavailable.
  • bash format.sh ci could not run because pre-commit is unavailable.
  • NPU execution, actual graph capture/replay, and PCP+C8+PD model validation remain outstanding. This draft does not claim the hardware results reported in [BugFix][Attention] Fix C8 slot mappings under PCP and DCP #16664.

Implementation and PR preparation used AI assistance (Codex).

Align persistent global and gathered PCP slot buffers and the padding scalar with the normal block-table dtype during initialization. Add gather and dummy buffer regression coverage.

Validation: Python syntax and git diff --check passed. Runtime tests and format.sh ci remain unverified because PyTorch, pytest and pre-commit are unavailable. AI assistance: Codex.
Signed-off-by: recky-c <252898884+recky-c@users.noreply.github.com>
AI assistance: Codex. Comment-only change; git diff --check passed. format.sh ci is blocked by missing pre-commit.

Signed-off-by: recky-c <252898884+recky-c@users.noreply.github.com>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical dtype mismatch between MRV2 PCP output buffers and Ascend block-table slots. By ensuring the PCP buffers inherit the dtype from the block tables during initialization, the change prevents incorrect cache-write metadata generation on PD producers. The implementation preserves existing persistent buffer behavior required for graph capture while ensuring consistency across the operator pipeline.

Highlights

  • Dtype Alignment: Updated the Ascend PCP global and gathered slot buffers to dynamically match the dtype of the block_tables.slot_mappings, ensuring compatibility with C8 cache-write operators.
  • Padding Scalar Adjustment: Aligned the padding scalar dtype with the slot buffers to prevent type mismatch errors during metadata generation.
  • Regression Testing: Added a new parameterized test in test_pcp_manager_v2.py to verify that slot buffers correctly adopt the block-table dtype and maintain buffer address reuse.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@github-actions

Copy link
Copy Markdown
Contributor

👋 Hi! Thank you for contributing to the vLLM Ascend project. The following points will speed up your PR merge:‌‌

  • A PR should do only one thing, smaller PRs enable faster reviews.
  • Every PR should include unit tests and end-to-end tests ‌to ensure it works and is not broken by other future PRs.
  • Write the commit message by fulfilling the PR description to help reviewer and future developers understand.

If CI fails, you can run linting and testing checks locally according Contributing and Testing.


Tip

💡 Consider Linking a Related Issue or RFC

Your PR title contains the [BugFix] tag, indicating a bug fix or new feature.

Linking a related issue or RFC in the PR description is strongly encouraged — it gives reviewers helpful context and speeds up the review. You can use any of these keywords:

  • Fixes #<issue_number>
  • Closes #<issue_number>
  • Resolves #<issue_number>
  • Refs #<rfc_or_issue_number> (for RFCs)

🙏 Thanks for helping us keep the project well-organized!

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

Suggested PR Title:

[Ops][BugFix] Align PCP slot buffer dtypes with block tables

Suggested PR Summary:

### What this PR does / why we need it?

This PR aligns the dtypes of PCP-local output buffers (`_global_batch_slot_mappings`, `_gathered_kv_slot_mappings`, and `_pad_slot_id`) with the Ascend block-table slot mappings dtype to prevent potential issues with cache-write operators. Additionally, feedback was provided to defensively check if `_pad_slot_id` is not None and avoid redundant allocations if the dtypes already match.

### Does this PR introduce _any_ user-facing change?

No.

### How was this patch tested?

A unit test `test_pcp_slot_buffers_match_block_tables` was added in `tests/ut/worker/test_pcp_manager_v2.py` to verify that the buffers are correctly initialized with matching dtypes.

Comment on lines +82 to +92
if block_tables is not None:
slot_dtype = block_tables.slot_mappings.dtype
if self._global_batch_slot_mappings is not None:
self._global_batch_slot_mappings = torch.empty_like(
self._global_batch_slot_mappings, dtype=slot_dtype
)
if self._gathered_kv_slot_mappings is not None:
self._gathered_kv_slot_mappings = torch.empty_like(
self._gathered_kv_slot_mappings, dtype=slot_dtype
)
self._pad_slot_id = self._pad_slot_id.to(slot_dtype)

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.

high

To adhere to defensive programming practices and optimize memory usage, we should:

  1. Ensure self._pad_slot_id is not None before calling .to(slot_dtype) to prevent potential runtime errors.
  2. Avoid redundant tensor allocations by checking if the existing dtypes of self._global_batch_slot_mappings and self._gathered_kv_slot_mappings already match slot_dtype before calling torch.empty_like.
Suggested change
if block_tables is not None:
slot_dtype = block_tables.slot_mappings.dtype
if self._global_batch_slot_mappings is not None:
self._global_batch_slot_mappings = torch.empty_like(
self._global_batch_slot_mappings, dtype=slot_dtype
)
if self._gathered_kv_slot_mappings is not None:
self._gathered_kv_slot_mappings = torch.empty_like(
self._gathered_kv_slot_mappings, dtype=slot_dtype
)
self._pad_slot_id = self._pad_slot_id.to(slot_dtype)
if block_tables is not None:
slot_dtype = block_tables.slot_mappings.dtype
if self._global_batch_slot_mappings is not None and self._global_batch_slot_mappings.dtype != slot_dtype:
self._global_batch_slot_mappings = torch.empty_like(
self._global_batch_slot_mappings, dtype=slot_dtype
)
if self._gathered_kv_slot_mappings is not None and self._gathered_kv_slot_mappings.dtype != slot_dtype:
self._gathered_kv_slot_mappings = torch.empty_like(
self._gathered_kv_slot_mappings, dtype=slot_dtype
)
if self._pad_slot_id is not None:
self._pad_slot_id = self._pad_slot_id.to(slot_dtype)

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has conflicts, please resolve those before we can evaluate the pull request.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant