[Bug][ROCm]: ROCM_ATTN sliding-window kernels output NaN when an out-of-window KV slot holds NaN/Inf

该问题出现在 ROCm 上使用 ROCM_ATTN 后端、模型含 sliding-window 层(尤其是混合模型或非因果 drafter)时,输出出现 NaN 但不报错。 ROCM_ATTN 的 Triton kernel 在计算 p @ v 时未屏蔽窗口外 key 的 V,若该槽位被其他请求或

快速结论:该问题出现在 ROCm 上使用 ROCM_ATTN 后端、模型含 sliding-window 层(尤其是混合模型或非因果 drafter)时,输出出现 NaN 但不报错。ROCM_ATTN 的 Triton kernel 在计算 p @ v 时未屏蔽窗口外 key 的 V,若该槽位被其他请求或 mamba state 复用为 NaN/Inf,则 0 * NaN = NaN 污染整行输出。优先排查:是否走 V2 model runner、是否已包含 #60767 修复、并发下是否释放并复用了窗口外 block。

适用环境:MI355X(gfx950),镜像 vllm/vllm-openai-rocm:nightly-rocm100-0cbac6cd1(vLLM 0.30.1rc1.dev558);涉及 vLLM 自带 Triton kernel,其他 ROCm GPU 同样受影响。复现配置:Qwen3.8-27B + z-lab/Qwen3.8-27B-DFlash2,ROCM_ATTN(target 与 drafter 均使用),MRV2,1024 output tokens,temperature 0。

最快修复方案:升级到包含 #60767(2026-10-19 合并)的主干版本。该改动让 V2 model runner 把完全位于滑动窗口以下的 block-table 条目指向 null block,kernel 不再读取已被复用为其他请求或 mamba state 的已释放 block。已在 main 00b6c4c565 上验证。

注意事项:#60767 只覆盖 V2 model runner;DFlash2 仅在 V2 runner 上运行,因此本 Issue 报告的场景已被覆盖。kernel 本身仍会无掩码加载窗口外 key 的 V,V1 model runner 没有对应修复,理论上仍可能触发,但暂无已知案例;#62415(在 kernel 中屏蔽 V)也因此关闭。若在 V1 runner 上复现,可重新打开该 Issue。

问题场景

在 ROCm 环境用 vLLM 服务一个带 sliding-window 层的模型,并选择 ROCM_ATTN 后端;典型场景是混合模型 Qwen3.8-27B 搭配 DFlash2 非因果 drafter(2048 token 窗口),开启 MRV2、temperature 0。并发较高时 KV cache 中完全位于窗口外的 block 被释放并被其他请求(或 mamba state)复用,随后 ROCM_ATTN 的 prefill 上下文计算(context_attention_fwd)和 decode 计算(HIP paged-attention 不可用时的 kernel_paged_attention_2d)读入这些槽位,attention 输出出现 NaN 且不抛错。单并发时释放/复用较少,问题不易暴露。

报错原文

[Bug][ROCm]: ROCM_ATTN sliding-window kernels output NaN when an out-of-window KV slot holds NaN/Inf

原因分析

已确认原因:ROCM_ATTN 的两个 Triton kernel(prefix_prefill.py 中的 context_attention_fwd、chunked_prefill_paged_decode.py 中的 kernel_paged_attention_2d)对滑窗外的 key 只把 score 掩蔽为 0,但加载 V 时没有掩码,仍会计算 p @ v。KV cache manager 会释放完全位于窗口外的 block,这些 block 可能被其他请求复用,在混合模型中甚至存放 mamba state。一旦其中是 NaN/Inf,0 * NaN = NaN,整行输出变 NaN。对照 TRITON_ATTN 已对滑窗外 key 的 V 做掩码(triton_unified_attention.py 中的 sw_mask_v),切换到 TRITON_ATTN 时 DFlash2 acceptance 正常。

修复思路:#60767 在 V2 model runner 层避免读取这些被复用的已释放 block,从源头消除 NaN/Inf 进入 kernel 的可能。

环境排查

  • 确认 vLLM 版本是否包含 #60767(2026-10-19 合并);可用对照:main 00b6c4c565 已包含且验证通过。
  • 确认是否运行在 V2 model runner 上;DFlash2 仅支持 V2 runner,#60767 的修复也只覆盖 V2 runner。
  • 确认 attention 后端是否为 ROCM_ATTN,并确认模型是否含 sliding-window 层(混合模型、非因果 drafter 风险最高)。
  • 确认复现并发度:单并发下 block 释放/复用少,问题可能不出现;建议提高到 16 并发测试。
  • 确认 ROCm 版本、GPU 型号(Issue 验证环境为 MI355X / gfx950)、镜像 tag 与 vLLM commit。
  • 用 TRITON_ATTN 做对照:若 acceptance length 恢复正常,可佐证问题出在 ROCM_ATTN 路径。

解决步骤

  1. 将 vLLM 升级到包含 #60767 的主干版本(合并于 2026-10-19),或直接使用含后续提交的镜像。
  2. 确保走 V2 model runner:本 Issue 的修复位于 V2 runner 的 block-table 处理逻辑中,V1 runner 没有对应改动。
  3. 保持原配置复测:MI355X、Qwen3.8-27B + z-lab/Qwen3.8-27B-DFlash2、ROCM_ATTN、MRV2、8k 输入、并发 16、1024 output tokens、temperature 0。
  4. 若仍遇到 NaN,确认是否在 V1 runner 上运行含 sliding-window 层的模型并使用了 ROCM_ATTN;如有,收集复现信息并重新打开 Issue #62828。
  5. 作为对照验证,可临时切换 TRITON_ATTN(它已对滑窗外 V 做掩码),观察 NaN 是否消失。

验证方法

用上面的复现配置跑 8k 输入、并发 16,观察 DFlash2 acceptance length 与吞吐。Issue 中报告:修复前 acceptance length 为 1.21、output tok/s 为 132.5;修复后(main 00b6c4c565)为 3.22、225.3;仅回退 #60767 时降至 1.19,可作为回归对照基线。同时确认日志中不再出现 NaN attention 输出,且 draft 未被整批拒绝。单并发(8k、并发 1)修复前后均正常,不适合作为验证场景。

参考来源

vllm-project/vllm #62828

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 30356

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注