Skip to content

[Bugfix][MoE][XPU] Gate topk_id=-1 padding sentinel on XPU (stopgap for vllm-xpu-kernels#572) - #71

Closed
afierka-intel wants to merge 2 commits into
mainfrom
afierka/fix-wna16-triton-gptq-marlin-fallback-layout
Closed

[Bugfix][MoE][XPU] Gate topk_id=-1 padding sentinel on XPU (stopgap for vllm-xpu-kernels#572)#71
afierka-intel wants to merge 2 commits into
mainfrom
afierka/fix-wna16-triton-gptq-marlin-fallback-layout

Conversation

@afierka-intel

@afierka-intel afierka-intel commented Sep 3, 2026

Copy link
Copy Markdown
Owner

What

New Platform.supports_moe_padding_sentinel() (default True). XPU overrides to False; both top-k routers gate topk_id = -1 emission on it instead of the raw VLLM_MOE_SKIP_PADDING env var. Check consolidated into base_router.get_padding_mask() (no @functools.cache — caching a platform+env check is unsafe under monkeypatching).

Why — stopgap for vllm-xpu-kernels#572, not a permanent fix

SYCL moe_align_block_size never gained the expert_id < 0 guard CUDA has. topk_id = -1 (padding sentinel, emitted whenever VLLM_MOE_SKIP_PADDING is on — default) is used as a raw index, writing out of bounds in _count_and_sort_expert_tokens and the small-batch-expert path. Depending on overflow size: silent weight corruption or device crash. Not WNA16-specific — any Triton MoE on XPU going through this kernel is exposed.

The real fix is vllm-project/vllm-xpu-kernels#572 (adds the guard at all 4 unguarded sites). This PR is a temporary shield for vllm-xpu-kernels builds that predate vllm-project#572 — remove it once vllm-project#572 ships in a released wheel that requirements/xpu.txt pins.

Not a duplicate: vllm-project#50759 covers routers without native padding support (different gap); vllm-project#42034 fixes the same "-1 as index" hazard in FlashInfer NVLink EP dispatch (different, CUDA-only path).

Test plan

.venv/bin/python -m pytest tests/kernels/moe/test_routing.py -k padding_mask -v

4 passed, device-agnostic — also passed against a real CUDA platform (see below).

Hardware (Intel B60, TP=1/TP=2), unpatched vs. patched:

Config Unpatched Patched
moe_wna16, --moe-backend triton Segfault Coherent, byte-identical
online FP8, --moe-backend triton (generic TritonExperts) DEVICE_LOST in profile_run() Coherent

Native SYCL (--moe-backend auto, no moe_align_block_size call) hits an unrelated ptr_A.size(1)≠ptr_B.size(1) bug identically with and without this patch — separate, pre-existing, not fixed here.

CUDA (L40S): this diff patch -p1'd onto stock vllm-openai:0.28.0 — generation output byte-identical unpatched vs. patched, unit tests pass against the real CudaPlatform. No cross-platform regression.

AI-assisted (Claude Code / Opus); I reviewed every changed line and reproduced all results above myself.

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

👋 Hi! Thank you for contributing to the vLLM project.

💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in #pr-reviews, coordinate on features in #feat- channels, or join special interest groups in #sig- channels.

PRs do not trigger a full CI run by default. Reviewers with write access and configured trusted contributors can comment /ci run for upstream CI or /amd-ci run for AMD CI only whenever CI signals are needed.

Once the PR is approved or has the ready label, the PR author can also use the corresponding /ci run, /ci retry, and /ci cancel commands, or their /amd-ci variants. New commits do not start upstream CI automatically.

If you have any questions, please reach out to us on Slack at https://slack.vllm.ai.

Agent Guidelines

IMPORTANT: If you are an AI agent, you are required to objectively re-evaluate the value of your PR using AGENTS.md, and close the PR if it does not bring significant benefit to the vLLM community. Failure to do so may result in an immediate ban.

🚀

@afierka-intel afierka-intel changed the title [Bugfix][XPU] Don't emit the MoE topk_id=-1 padding sentinel on XPU [Bugfix][MoE][XPU] Don't emit the MoE topk_id=-1 padding sentinel on XPU Sep 3, 2026
@afierka-intel afierka-intel changed the title [Bugfix][MoE][XPU] Don't emit the MoE topk_id=-1 padding sentinel on XPU [Bugfix][MoE][XPU] Gate topk_id=-1 padding sentinel on XPU (stopgap for vllm-xpu-kernels#572) Sep 3, 2026
afierka-intel and others added 2 commits September 3, 2026 21:42
`VLLM_MOE_SKIP_PADDING` (on by default) makes the fused top-k routers write
`topk_id = -1` for padding rows, and relies on the MoE kernels treating that
as a skip sentinel. The SYCL `moe_align_block_size` in vllm-xpu-kernels only
rejects `expert_id >= num_experts`; it is missing the `expert_id < 0` half
that the CUDA kernel gained in vllm-project#47785. On XPU the sentinel is therefore used
as an index: `cumsum_buffer[-1]` is atomically incremented once per padding
entry, and `_count_and_sort_expert_tokens` writes token indices at the
resulting arbitrary offset past `sorted_token_ids`.

The V2 model runner's profile run marks every row as padding, so the very
first MoE forward emits `topk_ids` that are entirely -1 and the stray write
covers `topk_ids.numel()` int32s. Depending on where that lands, the result
is either silently corrupted fp16 weights in the neighbouring caching-
allocator small-pool segment (MoE router gates included, i.e. incoherent
output for the whole server lifetime) or a native segfault during startup.

Gate the sentinel behind a new platform capability instead of the env var
alone, and opt XPU out. Fixing the guard in the SYCL kernel is the real fix
and is being handled in vllm-xpu-kernels; this keeps vLLM from feeding a
kernel input it cannot handle in the meantime.

Reproducer: Qwen/Qwen1.5-MoE-A2.7B-Chat-GPTQ-Int4 on Arc Pro B60, TP=1,
fp16, `--quantization moe_wna16 --moe-backend triton` (TritonWNA16Experts).
Before: segfault in the profile run, 100% of runs. After: coherent output,
3/3 runs; `--moe-backend auto` (XPUExpertsWNA16) unaffected either way.

Assisted-by: Claude Opus 5 (Claude Code)
Signed-off-by: Artur Fierka <artur.fierka@intel.com>
…l gate

- Drop the @functools.cache on the padding-sentinel check: caching a
  platform-capability + env-var read is unsafe across tests/platforms
  that monkeypatch either one at runtime.
- Consolidate the duplicated skip-padding helper (previously copy-pasted
  in fused_topk_router.py and fused_topk_bias_router.py) into a single
  base_router.get_padding_mask(), imported by both.
- Add a device-agnostic unit test covering all four gate outcomes
  (env off, platform unsupported, no forward context, mask returned).
- Broaden the XPU comment and the interface.py docstring: the exposure
  also covers moe_align_block_size's small-batch-expert variant, which
  has no bound check at all (not just the missing `< 0` guard on the
  large-batch path this PR was validated against).

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Artur Fierka <artur.fierka@intel.com>
@afierka-intel
afierka-intel force-pushed the afierka/fix-wna16-triton-gptq-marlin-fallback-layout branch from 814e6e8 to 10b2ef5 Compare September 3, 2026 19:43
@afierka-intel

Copy link
Copy Markdown
Owner Author

Superseded — published upstream as vllm-project#55231.

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