开源贡献推理优化源码分析

78 万次查询,零命中:我给 vLLM 提了个 bug

2026-10-03 · PM Parker · 阅读约 8 分钟

先看一个荒诞的数字:788,000 比 0。

这是我推理服务上 prefix caching 的查询计数器。78 万多次查询,命中零次。

这个功能是开着的。配置里写着开。

背景:prefix cache 为什么重要

跑大模型对话服务,多轮对话的性能全指望它。用户第二轮提问时,前面几轮的上下文不用重新计算,从缓存里增量续算就行。

没有它,每一轮都是冷启动:首字延迟和上下文长度成正比,对话越长,每一轮等得越久。

我的场景恰好是多轮长上下文,所以当时部署完就把它打开了,还专门确认过启动参数里没有那个禁用开关。

然后我发现多轮对话的首字延迟完全不符合预期。做实验:同一段 13K token 的 prompt,原样发三次。

三次首字延迟:15.9 秒、15.9 秒、15.9 秒。

如果缓存存在,第二三次应该明显更快。数字纹丝不动,说明每次都在冷启动。

先怀疑自己,再怀疑世界

按排查纪律,我先花时间排除了自己的问题:开关确认开启、版本核对、发请求的方式核对。都对。

然后去 GitHub 找同类。还真有:一个 H200 环境下的已知报告,症状几乎一样,DeepSeek-V4-Flash 的混合 KV 分组里,前缀块会被重分配销毁,导致命中长度塌缩成零。

但对照做完,发现我们的情况更糟。那个 issue 的环境里,紧挨着重发同一个请求是能命中的;而我们连紧邻重发都不命中。

这说明我们碰到的是更深一层的东西。

翻源码:这条路径上没有缓存的代码

于是去翻源码。翻完之后,事情变得很清楚,也很无奈。

我们这套 Thor 设备上的推理路径,是部署方自己维护的私有分支:上游 vLLM 的主仓库里根本没有对应的实现文件,硬件支持列表里也没有这块芯片的身影。

而分支里的实现,把所有后端变体都路由到了同一个注意力类上,这个类走的是 Triton 的退化方案,里面压根没有 prefix 查询的逻辑。

也就是说:开关开了,请求也来问了,但这条路径上从来没有实现过查询这件事。78 万次查询,问的是一个不存在的东西。

配置开着,不代表功能存在。开关和实现,是两回事。

报一个合格的 bug

定位清楚了,下一步是提交给谁。上游主仓库不包含这条路径,但问题真实存在,所有用这套部署的用户都会踩。我把三样东西整理成了一份报告:

复现数据:78 万次查询零命中的计数器、同段 prompt 三次 15.9 秒的延迟记录。

定位分析:源码层面说明这条 Thor 路径的注意力实现里没有 prefix 查询逻辑。

对照材料:关联上游已知的 H200 变体 issue 和 roadmap 讨论,说明不是重复报告,是覆盖缺失。

8 月 31 日晚上 8 点 40 提交。就在当天下午整机复位风波之后的几个小时,那一天的服务器很热闹。

issue 目前还挂着。短期方案我也认了:接受冷启动,把多轮对话的上下文控制在能忍的范围里。

三件事带走

第一,遇到"配置开了不生效",先别急着改配置。配置只是申请,功能存在才发放。去确认实现里到底有没有这段代码。

第二,用 fork 的时候心里要有数:上游的修复到不了你,你的 bug 也别指望别人顺手修。私有路径的每一个坑,都是你自己的。

第三,报 bug 的规格是三件套:能复现的数据、定位到的分析、和已知问题的对照。少了任何一样,维护者都得多花一小时,或者干脆不花。

那个计数器后来一直在涨,还是零命中。看着它,就像看着一部永远占线的电话。

你给开源项目报过最有意思的 bug 是什么?来聊聊。


← 返回博客列表 · 相关阅读:慢的三层真相 · 配置被平台覆盖回退