Skip to content

[Bugfix] Route DSv4 sparse-indexer prefill top-k around NaN-broken kernel path on SM12x - #49897

Open
linjiapro wants to merge 1 commit into
vllm-project:mainfrom
linjiapro:fix/sm120-topk-prefill-uninitialized-smem
Open

[Bugfix] Route DSv4 sparse-indexer prefill top-k around NaN-broken kernel path on SM12x#49897
linjiapro wants to merge 1 commit into
vllm-project:mainfrom
linjiapro:fix/sm120-topk-prefill-uninitialized-smem

Conversation

@linjiapro

@linjiapro linjiapro commented Jul 26, 2026

Copy link
Copy Markdown

FIX #49896 (the crash layer; the NaN-logits layer of that issue remains open).

Purpose

DeepSeek-V4-Flash on SM12x (enabled by #43477) crashes with a CUDA illegal memory access on the first prefill longer than ~2048 tokens. Root cause chain (full tensor-level evidence in #49896):

  1. fp8_fp4_mqa_logits emits NaN-dominated logits on SM12x (83→100% NaN cascade).
  2. top_k_per_row_prefill's histogram path (rows with more candidates than top_k) mishandles NaN input: it writes NaN bit patterns (0x7FC00000 = 2143289344) as candidate indices and leaves part of its dynamic-smem output unwritten, copying uninitialized memory out as indices. Reproducible in a 25-line standalone script (see the issue); with clean input the kernel is correct on SM120 (upstream unit test passes 12/12 here).
  3. compute_global_topk_indices_and_lens trusts local_idx >= 0 and gathers block_table[req, INT32_MAX // block_size] → IMA on all TP ranks.

This PR routes SM12x prefill top-k through a torch.topk implementation of the kernel's documented contract: top-k of logits[i, ks_i:ke_i) relative to ks_i, ascending position order, -1 padding for short rows, NaN never selected. It mirrors the decode path, which already excludes SM12x from cooperative_topk.

Deliberately narrow:

  • Not a csrc change: the kernel's NaN mishandling is data-driven and deserves hardening for every arch (never emit unwritten smem; exclude NaN), but we cannot build/test csrc on the affected hardware — left to the issue.
  • Not a fix for the NaN logits themselves (the primary SM12x defect; cf. the e8m0→fp32 upcast and SM120 DeepGEMM fallbacks in [New Model][Nvidia] Add SM12x support for DeepSeek V4 Flash with essential fixes #41834). With NaN scores, any correct top-k selects an arbitrary candidate set, so SM12x DSv4 output quality for long prompts remains degraded until that lands. This PR converts a hard engine crash into defined, contract-correct behavior and is a prerequisite for any further SM12x DSv4 work.

Test Plan

  • New contract test test_top_k_per_row_prefill_torch_fallback (runs on any CUDA device): set-equality with the torch.topk reference per row, ascending order, in-range, -1 padding, NaN exclusion.
  • Real-workload validation on 4× RTX PRO 6000 Blackwell Workstation (SM120, TP=4), vLLM 0.26.0 + flashinfer 0.6.14, DeepSeek-V4-Flash: the previously 9×-reproducible crash (16 concurrent structured-output requests, mixed 0.5–8K-token prefill) is eliminated — zero illegal memory accesses, zero garbage indices in the consumer across repeated full fan-outs; engine survives and serves.

Test Result

  • test_top_k_per_row_prefill_torch_fallback: 6/6 pass on SM120.
  • Existing test_top_k_per_row (CUDA kernel, clean inputs): 12/12 pass on SM120, unaffected by this change.

… path on SM12x

On SM12x, serving DeepSeek-V4-Flash crashes with a CUDA illegal memory
access on the first prefill longer than ~2048 tokens (or any concurrent
prefill batch reaching that length). Root cause chain, isolated on
4x RTX PRO 6000 Blackwell Workstation (TP=4, vLLM 0.26.0):

1. fp8_fp4_mqa_logits emits NaN-dominated logits on SM12x (83% NaN on
   the first C4A layer, 100% after the cascade).
2. top_k_per_row_prefill's histogram path (rows with more candidates
   than top_k) mishandles NaN input: it writes NaN bit patterns
   (0x7FC00000 = 2143289344) as candidate indices and leaves part of
   its dynamic-shared-memory output unwritten, so uninitialized memory
   is copied out as indices. Reproducible in isolation with clean
   inputs producing 0 garbage rows and 83%-NaN inputs producing
   garbage in ~40% of histogram-path rows.
3. compute_global_topk_indices_and_lens treats any index >= 0 as valid
   and dereferences block_table[req, idx // block_size] -> illegal
   memory access, killing all TP workers.

Route SM12x prefill top-k through a torch.topk implementation of the
kernel's documented contract (top-k of logits[i, ks:ke) relative to ks,
ascending position order, -1 padding, NaN never selected) — mirroring
the decode path, which already excludes SM12x from cooperative_topk.
Verified on the affected hardware: the previously 9x-reproducible crash
is eliminated across 16-way concurrent structured-output fan-outs.

The kernel's NaN mishandling is data-driven and likely arch-independent;
hardening it in csrc (never emit unwritten smem, exclude NaN) and the
SM12x NaN-logits defect itself are tracked separately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Lin Jia <linjiapro@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.

@github-actions

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. Once the PR is approved and ready to go, your PR reviewer(s) can run CI to test the changes comprehensively before merging.

To run CI, PR reviewers can either: Add ready label to the PR or enable auto-merge.

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.

🚀

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] DeepSeek-V4 on SM12x: NaN MQA logits drive top_k_per_row_prefill to emit uninitialized smem as indices -> illegal memory access

1 participant