[Bug]: int8_per_token_head scale-view fill overwrites Gated DeltaNet state in hybrid models

这个报错通常发生在 vLLM 混合模型(含 Gated DeltaNet 层与全注意力层)配合 --kv-cache-dtype int8_per_token_head 和 TRITON_ATTN 后端时,表现为引擎启动后的第一次请求从第二个 token 起输出乱码。优先排查 _ensure_sca

快速结论:这个报错通常发生在 vLLM 混合模型(含 Gated DeltaNet 层与全注意力层)配合 --kv-cache-dtype int8_per_token_head 和 TRITON_ATTN 后端时,表现为引擎启动后的第一次请求从第二个 token 起输出乱码。优先排查 _ensure_scale_caches 中的 fill_ 初始化是否会覆盖 Gated DeltaNet 的循环状态。

适用环境:Issue 确认环境为 vLLM 0.32.0(从 sdist 构建,sm_70),Tesla V100 PCIe 32 GB,驱动 580.196.07,CUDA 12.9,torch 2.13.0+cu126;模型 RedHatAI/Qwen3.8-27B-INT4(48 层 Gated DeltaNet + 16 层全注意力)。评论中另有 RTX 4090 24GB(BF16,MRV2 eager,TRITON_ATTN,INT8 per-token-head KV,开启 prefix caching)的复现记录。复现使用 --kv-cache-dtype int8_per_token_head --attention-backend TRITON_ATTN --enable-prefix-caching。

最快修复方案:升级到包含 #56492 修复的 main;该修复移除了 _ensure_scale_caches 中两处 fill_(1.0) 调用。若停留在发布版,可参考 Issue 用户的临时做法:覆盖 _ensure_scale_caches,只创建 torch.as_strided 视图而不写入。

注意事项:v0.33.0rc3 所在 releases/v0.33.0 分支截至该版本仍保留两处 fill,除非有 backport,否则 0.33.0 仍会触发此问题。Issue 报告者尚未在 main 上实际验证,仅确认 out-of-tree 覆盖方法在其 V100 上修复了第一次请求。

问题场景

用户使用 vLLM 0.32.0 加载 Qwen3.5 系混合模型,启用 int8_per_token_head 的 KV cache 量化、TRITON_ATTN 后端和前缀缓存。引擎启动后第一次请求从第二个 token 开始变成乱码,之后所有请求正常;改用 --kv-cache-dtype auto 时第一次请求也正常。评论中在 Qwen3.5-4B + RTX 4090 上同样复现。

报错原文

[Bug]: int8_per_token_head scale-view fill overwrites Gated DeltaNet state in hybrid models

The first request after engine start turns to garbage from its second token.
Every later request is correct. With `--kv-cache-dtype auto` the first request
is correct too.

原因分析

最可能的原因是 TritonAttentionImpl._ensure_scale_caches 在层首次运行时创建 per-token-head 的 scale 视图,并用 fill_(1.0) 初始化:

self._k_scale_cache.fill_(1.0)
...
self._v_scale_cache.fill_(1.0)

在这类混合模型中,KV cache manager 让注意力层与 Gated DeltaNet 层共享同一批物理页。由于 dummy run 跳过 attention(Issue 引用了 #51091),第一个注意力层直到第一次真实前向时才创建视图,而排在它之前的 Gated DeltaNet 层已经把循环状态写进这些页,随后的 fill 用 1.0 覆盖了部分状态。#51091 的“每个视图只初始化一次”方案无法覆盖本场景,因为该视图的第一次也是唯一一次 fill 已经发生在其他层类型写入之后。

环境排查

  • 确认 vLLM 版本是否为 0.32.0 或仍带两处 fill_(1.0) 的构建;检查是否已包含 #56492。
  • 确认 --kv-cache-dtype 是否为 int8_per_token_head,可先用 auto 对照第一次请求是否正常。
  • 确认 --attention-backend 为 TRITON_ATTN,以及是否开启 --enable-prefix-caching。
  • 确认模型为含 Gated DeltaNet 层与全注意力层的混合架构(如 Qwen3.5 系),并确认量化 INT4/INT8 权重加载正常。
  • GPU 架构与算力:Issue 环境为 sm_70(Tesla V100),评论复现环境为 RTX 4090;代码路径报告称与架构无关。
  • 记录 torch(2.13.0+cu126)、CUDA(12.9)与驱动(580.196.07)版本,便于对照。

解决步骤

  1. 先做对照:用 --kv-cache-dtype auto 启动同一模型,确认第一次请求是否正常。若正常,基本可锁定为 int8 scale 初始化路径问题。
  2. 优先升级到包含 #56492 的 main,或使用已 backport 该修复的发行版构建。该修复删除 _ensure_scale_caches 中两处 fill_(1.0),不改动视图创建逻辑。
  3. 若暂时不能升级,可优先尝试 Issue 用户的 out-of-tree 临时方案:覆盖 _ensure_scale_caches,仅构建 torch.as_strided 视图,不执行任何写入。这属于未合入上游的 workaround,需自行承担维护成本。
  4. 如需在上游代码中保留初始化,应按 Issue 建议把初始化放到 KV pool 分配阶段,早于任何层写入;不要在首次前向时按视图填充。
  5. 不要仅依赖 #51091 的修复;它只保证每个视图初始化一次,不能避免“初始化发生在 GDN 写入之后”。

验证方法

启动引擎后立即发送第一次请求,观察是否仍从第二个 token 开始出现乱码;后续请求应保持正确。可与 --kv-cache-dtype auto 的输出逐 token 对比。Issue 中另用哨兵测试验证:不带 fill 创建视图时缓存字节不变,而带 fill 的方法会修改缓存字节。若使用临时覆盖方案,还应确认 K/V 量化误差在报告范围内(K 约 1.0–1.5%,V 约 0.9–2.4% 相对误差)。

参考来源

vllm-project/vllm #63944

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 33076

发表回复

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