Skip to content

[Perf][Ops] Fused mHC via AscendC npu_hc_pre_v2/npu_hc_post - #15429

Open
Liears wants to merge 4 commits into
vllm-project:mainfrom
Liears:glm53-pr-mhc-fused
Open

Liears wants to merge 4 commits into
vllm-project:mainfrom
Liears:glm53-pr-mhc-fused

Conversation

@Liears

@Liears Liears commented Aug 31, 2026 •

Copy link
Copy Markdown

What does this PR do?

Replaces ~340 eager dispatches per layer of mhc_pre_torch/mhc_post_torch (117 of them from the 20-round Sinkhorn normalisation) with two fused AscendC kernels:

  • npu_hc_pre_v2: mix projection + RMS-normalised gates + 20-round Sinkhorn + stream contraction in ONE launch
  • npu_hc_post: comb @ residual + post ⊙ x

4 launches per layer instead of ~340. py-spy measured mhc_pre_torch at 43% of worker host time on GLM-5.3-Flash.

Keeps the upstream MHCPreOp/MHCFusedPostPreOp return contract, fuses the layer input RMSNorm, and falls back to the torch path when the operator is unavailable or shapes are outside the envelope (hc_mult<=4, d in {4096,7168}, bf16 x / fp32 hc params). Env switch GLM53_HC_ASCENDC (default on).

New file only (ops module + unit tests); the patch wiring is a separate PR.

Performance

GLM-5.3-Flash W8A8, 8x Atlas A2, TP8, eager: mHC host share 43% → <4%. Unit tests cover numeric parity vs the torch reference (29 checks, within 0.5 bf16 ulp).

Does this PR introduce any user-facing change?

No API change; opt-out env switch preserved.

🤖 Generated with Claude Code

@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 introduces high-performance fused AscendC kernels for the mHC (multi-hyper-connection) operations in GLM-5.3-Flash, significantly improving inference performance by reducing eager dispatch overhead. It also adds comprehensive support for the model, including documentation, end-to-end testing, and critical compatibility fixes for KV cache management and upstream vLLM API changes.

Highlights

  • Fused AscendC Kernels: Replaced ~340 eager dispatches per layer with two fused AscendC kernels (npu_hc_pre_v2 and npu_hc_post), reducing host-side overhead for mHC operations from 43% to <4%.
  • GLM-5.3-Flash Support: Added full support for GLM-5.3-Flash, including model documentation, E2E test configurations, and necessary compatibility patches for upstream vLLM import signatures and KV cache specifications.
  • MLA-NoPE Compatibility: Implemented robust handling for MLA-NoPE architectures (e.g., zero-width RoPE cache) and added regression tests to ensure compatibility with upstream vLLM structures.
  • Quantization and Memory: Optimized FP8 quantization handling for GLM-5.3-Flash, including correct MXFP8 scale packing and improved ModelSlim configuration for draft models.
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.

@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

This pull request introduces support for serving the GLM-5.3-Flash model on Ascend NPUs, adding documentation, tutorials, and critical compatibility fixes for MLA-NoPE, Mamba-family layers, and upstream vLLM imports.

Suggested PR Title:

[Attention][Feature] Support GLM-5.3-Flash serving on Ascend NPUs

Suggested PR Summary:

### What this PR does / why we need it?
This PR adds comprehensive support for serving the GLM-5.3-Flash model on Ascend NPUs. It introduces tutorials, updates feature guides, and implements critical compatibility and performance enhancements. Key changes include:
- Integrating fused mHC (multi-hyper-connection) operators (`npu_hc_pre_v2` and `npu_hc_post`) to reduce host-side overhead.
- Fixing MLA-NoPE chunked-context paged gather when `qk_rope_head_dim == 0` to avoid zero-width operand issues.
- Correcting `bind_kv_cache` dispatch to ensure Mamba-family layers unpack raw allocations properly.
- Resolving upstream vLLM import and signature compatibility issues, such as `skip_gather` in the logits processor and `storage_block_size` in `MLAAttentionSpec`.

### Does this PR introduce _any_ user-facing change?
Yes, it adds support for serving the GLM-5.3-Flash model on Ascend NPUs.

### How was this patch tested?
Unit tests have been added to verify MLA-NoPE chunked-context paged gather, upstream import compatibility, KV cache spec compatibility, KDA gate, and mHC AscendC operators.

Review Feedback:

  1. Critical Bug: In vllm_ascend/ops/triton/mamba/causal_conv1d.py, the function causal_conv1d_update_npu_DISABLED must be renamed to causal_conv1d_update_npu to match the import in patch_triton.py, otherwise the optimized NPU Triton implementation will fail to load.
  2. Performance Issues: In vllm_ascend/ops/triton/kda/kda.py, avoid calling .item() on slot[0] (lines 203 and 224) as it triggers host-device synchronization and breaks graph capture in the speculative decoding hot path. Index initial_state directly with slot[0] instead.
  3. Test Robustness: In tests/ut/ops/test_mhc_ascendc.py, avoid hardcoding absolute paths to external model configuration files. Define standard configuration constants directly in the test file to make it self-contained.

return x[:, indices].permute(1, 0, 2)


def causal_conv1d_update_npu_DISABLED(

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.

critical

The function is named causal_conv1d_update_npu_DISABLED in this file, but vllm_ascend/patch/worker/patch_triton.py attempts to import causal_conv1d_update_npu. This mismatch causes the import to fail silently (caught by a try-except block) and prevents the optimized NPU Triton causal conv1d update from being used, which is a critical performance issue. Please rename the function to causal_conv1d_update_npu to match the import.

Suggested change
def causal_conv1d_update_npu_DISABLED(
def causal_conv1d_update_npu(

Comment thread vllm_ascend/ops/triton/kda/kda.py Outdated
Comment on lines +203 to +205
committed = initial_state[
int(slot[0].item())
].clone()

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

Calling .item() on slot[0] (which is an NPU tensor) triggers a host-device synchronization. This breaks graph capture and degrades performance in the speculative decoding hot path. Since PyTorch supports indexing with 0-D/1-D tensors on the same device, you can index initial_state directly with slot[0] without calling .item().

                committed = initial_state[slot[0]].clone()

Comment thread vllm_ascend/ops/triton/kda/kda.py Outdated
)
o_full[:, pos] = o_step[:, 0]
# Restore the state committed at the accepted boundary.
initial_state[int(slot[0].item())] = committed

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

Similarly to the state capture above, calling .item() here triggers a host-device synchronization. Index initial_state directly with slot[0] to keep the operation entirely on the device and graph-safe.

Suggested change
initial_state[int(slot[0].item())] = committed
initial_state[slot[0]] = committed

Comment thread tests/ut/ops/test_mhc_ascendc.py Outdated
Comment on lines +39 to +48
CONFIG_PATH = "/mnt/public/models/GLM-5.3-Flash-BF16/config.json"
DEVICE = "npu"

CFG = json.load(open(CONFIG_PATH))["text_config"]
HIDDEN = CFG["hidden_size"] # 4096
HC_MULT = CFG["hc_mult"] # 4
MIX_HC = (2 + HC_MULT) * HC_MULT # 24
SINKHORN = CFG["hc_sinkhorn_iters"] # 20
RMS_EPS = CFG["rms_norm_eps"] # 1e-5
HC_EPS = CFG["hc_eps"] # 1e-6

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

Hardcoding an absolute path to an external model configuration file (/mnt/public/models/...) makes this unit test environment-dependent and will cause it to fail with FileNotFoundError in CI/CD or on other developers' machines. Since the configuration parameters are standard constants, they should be defined directly in the test file to make the test self-contained and robust.

DEVICE = "npu"\n\nHIDDEN = 4096\nHC_MULT = 4\nMIX_HC = (2 + HC_MULT) * HC_MULT  # 24\nSINKHORN = 20\nRMS_EPS = 1e-5\nHC_EPS = 1e-6

Liears added 2 commits August 31, 2026 13:43
Replace the ~340 eager dispatches per layer of mhc_pre_torch/mhc_post_torch
(including 117 Sinkhorn-iteration dispatches) with two fused AscendC kernels:
npu_hc_pre_v2 (mix projection + RMS-normalised gates + 20-round Sinkhorn +
stream contraction in ONE launch) and npu_hc_post. Keeps the upstream
MHCPreOp/MHCFusedPostPreOp return contract and fuses the layer input RMSNorm.
Falls back to the torch path when the operator is unavailable or shapes are
outside the envelope (hc_mult<=4, d in {4096,7168}, bf16 x / fp32 hc params).

This adds the ops module only; the patch_triton binding is a separate commit.

Signed-off-by: Liears <Liears@users.noreply.github.com>
29 checks: hc_pre/hc_post/fused_post_pre vs the torch reference, fallback
branches (unsupported shapes, env kill switch), and the skip branch.

Signed-off-by: Liears <Liears@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

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

@Liears
Liears force-pushed the glm53-pr-mhc-fused branch from a4dbee0 to 8abab51 Compare August 31, 2026 13:48
@Liears

Liears commented Sep 3, 2026

Copy link
Copy Markdown
Author

Addressed the review findings in 1754639:

  • Test path hardcoding (tests/ut/ops/test_mhc_ascendc.py): the config constants are now inlined (verified equal to the shipped GLM-5.3-Flash config.json) and the repo root is derived from __file__, so the test is self-contained and CI-safe.
  • causal_conv1d_update_npu_DISABLED naming / import mismatch: no longer present in the current tree — the branch was rebased past [Refactor][Ops] Remove causal_conv1d_update_npu #14620 (which removed causal_conv1d_update_npu), and no references remain anywhere in vllm_ascend/ or tests/.
  • .item() host syncs in kda.py: that spec-decode fallback decomposition was superseded by the AscendC recurrent_kda path; no .item() calls remain in vllm_ascend/ops/triton/kda/kda.py.

Liears and others added 2 commits September 3, 2026 06:27
Inline the GLM-5.3-Flash config constants (verified equal to the shipped
config.json) instead of reading /mnt/public/models/... at runtime, and derive
the repo root from __file__ instead of hardcoding /vllm-workspace, so the
test runs on any checkout and in CI.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Liears <liears@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Liears <liears@users.noreply.github.com>
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