# PR #47305 完整报告

- 仓库：`vllm-project/vllm`
- 标题：[Bugfix] Don't read KV cache past `seq_len` in triton paged attn kernels
- 合并时间：2026-07-02 03:43
- 原文链接：http://prhub.com.cn/vllm-project/vllm/pull/47305

---

# 执行摘要

- 一句话：修复 Triton paged attention 越界读 NaN 导致输出污染
- 推荐动作：建议立即合入。该 PR 修复了一个被 Claude 协助发现、WoosukKwon 称赞的精妙 bug，虽改动量小但正确性意义重大。值得精读其分析过程，理解 MRV2 预热与 KV cache 块尾 NaN 的交互。

# 功能与动机

修复 Triton paged attention 核在读取 KV cache 时可能越界读取未写入的块尾槽位，当这些槽位因 MRV2 预热不含 NaN 时（如 ROCm 上的编码器 - 解码器场景），0 * NaN = NaN 导致输出污染，表现为 Whisper 跨层注意力输出乱码。PR body 指出："reading beyond seq_len is never valid"，即使正常情况下越界读 0 也无害，但安全边界应确保正确性。

# 实现拆解

1. **`triton_attention_helpers.py`：限制非因果 / 混合分支的循环上界**
 - 在 `compute_tile_loop_bounds` 函数中，对于非因果、混合或前缀前缀批次的 `max_seq_prefix_len` 计算，将其从原来的 `tl.maximum(max_seq_prefix_len, seq_len)` 改为直接赋值为 `seq_len`。原因是因果推导出的 `max_seq_prefix_len` 可能超过实际序列长度，导致后续循环读取超出 seq_len 的槽位。

2. **`chunked_prefill_paged_decode.py`：对 K/V 加载增加掩码**
 - 在 `kernel_paged_attention_2d` 函数中，计算 `kv_load_mask = abs_token_idx < seq_len`，并在 K 和 V 的 `tl.load` 调用中，将原有的 `dim_mask` 与 `kv_load_mask` 按位与，确保跳过所有 >= seq_len 的槽位，从而即使块尾含有 NaN 也不会被加载。

3. **无测试 / 配置 / 部署配套改动 **（本 PR 仅为 2 个文件的简单 bugfix，改动量很小）。

关键文件：
- `vllm/v1/attention/ops/triton_attention_helpers.py`（模块 注意力核；类别 infra；类型 infrastructure；符号 compute_tile_loop_bounds）: 核心修复之一：修改 `compute_tile_loop_bounds`，将非因果 / 混合分支的 `max_seq_prefix_len` 限制为 `seq_len`，防止循环越界读取未写入的 KV cache 槽位。
- `vllm/v1/attention/ops/chunked_prefill_paged_decode.py`（模块 注意力核；类别 infra；类型 infrastructure；符号 kernel_paged_attention_2d）: 核心修复之二：在 `kernel_paged_attention_2d` 中增加 `kv_load_mask`，在 K/V 加载时跳过超出 seq_len 的槽位，避免 0 * NaN = NaN 污染输出。

关键符号：compute_tile_loop_bounds, kernel_paged_attention_2d


# 评论区精华

该 PR 无 review 评论线程，只有 claude bot 的自动回复（声明从 fork 来无法自动审查），以及 WoosukKwon 的批准评论：“Amazing. Thanks for getting to the bottom of this!” 没有公开讨论争议。

- 暂无高价值评论线程

# 风险与影响

- 风险：本 PR 是一个边界安全的 bugfix，改动量极小（+13/-6），且改动均是在原有逻辑上增加限制，不会破坏现有正确行为。潜在风险极低：
 - `compute_tile_loop_bounds` 中非因果分支使用 `seq_len` 而非 `maximum`，可能略微减少某些混合批次的最大循环次数，但 score mask 早已处理了因果边界，因此安全。
 - K/V 加载掩码增加 `& kv_load_mask`，其他值设为 0.0，与 score mask 一致，不会引入 NaN 毒化。
 - 未涉及性能关键路径的语义变更，性能影响可忽略。
 - 无测试覆盖（原文件不包含测试），但风险极小，可快速合入。
 - 影响：**影响范围**：修复了 Triton 统一注意力核与 ROCm paged-decode 核在特定场景下的 NaN 污染问题。

**影响程度**：
- 用户侧：消除 Whisper 等编码器 - 解码器模型在 ROCm（MRV2）下的输出乱码问题。
- 系统侧：修复了之前“靠 score mask 过滤垃圾”的隐式假设，使 KV cache 读取更安全。
- 团队侧：无迁移成本，无需用户操作。

**影响版本**：v1 引擎（MRV2），主要在 ROCm 平台。

- 风险标记：缺少测试覆盖

# 关联脉络

- PR #47071 [Bugfix] Fix pooled Whisper sliding-window KV sizing: 同一作者（njhill）修复 Whisper 跨层注意力问题，与本 PR 发现的 Whisper 在 ROCm 上输出乱码问题相关。
- PR #47029 [Bugfix] Prevent padding placeholders from reaching embeddings: 同样涉及 v1 引擎下投机解码的 KV cache 边界问题，与本 PR 主题相关。