方法学 · 解码吞吐 · 2× RX 7900 XT

离线探针与 campaign harness 吻合到 0.44 %,
此前四次运行中的首轮读数低了 31 %

这一对 Radeon 卡上的解码吞吐;在离线探针与 campaign harness 之间核对,跨越冷启动与三十天的漂移

本仓库中有两套 harness 会产出解码数据:一套离线探针,一套 campaign harness。图表若要汇总两者的结果,其间差异必须经由实测确立,而非凭空假定。在热机状态下,该差异仅为 0.44 %。查明这一点经历了四次完全相同的运行,因为首轮读数整整低了 31 %。

2× RX 7900 XT · gfx1100 · TP=2 用 Qwen3-8B · bf16 标定 170 条 ledger 记录 实测 2026-08-26

摘要

campaign harness 采用流式传输请求兼容 OpenAI 协议的服务端,在温度 0.8 下采样并生成 512 个 token。探针 harness 则离线调用 LLM.generate 走贪婪解码(greedy),以 64 个 token 的运行结果减去 8 个 token 的运行结果求差。在匹配的上下文深度上,两者的吻合度分别达到 0.44 %、0.01 % 与 0.07 %。将两者的生成长度统一也未带来实质性改变。它们记录的是同一次测量。

得出该结论的前提,是先认识到在这台机器上,一次运行不构成一次测量。连续四次完全相同的运行读数依次偏差 −30.7 %、−5.1 %,随后趋于收敛。性能惩罚在机器吞吐最高处最为严重,以至于起初将预热效应误判成了两套 harness 之间的实现差异。

由此引出两条规则,并直接固化在 ledger 中,而非留待绘图时任意裁量。每个数据点均记录 runs 与 range_pct。patches 字段采用列表而非布尔值,因为依赖未合并 PR 测出的结果,与直接基于公开发行版测出的结论,绝非同等性质的断言。

指标选用极差而非标准差,其中一个格子清楚地证明了原因。为一个在 8K 上呈现双峰分布的数据点增加第三和第四次运行后,其极差从 15.79 % 扩大至 16.79 %,但标准差反而由 4.87 降至 3.61。前者警告测量稳定性出现下降,后者却给出了测量质量有所改善的假象。

1两套 harness 测的是不是同一件事

选用该基准模型进行标定,目的十分明确:将两套 harness 的差异与整个技术栈中的其余变量完全隔离开来:

引擎各项运行参数严格沿用 campaign 的既有配置。上下文深度直接采用 campaign 所记录的 prompt_tokens 实际数值,而非标称目标值,从而确保两套 harness 始终在完全相同的序列长度下测量,而非仅停留在相近深度。

图 1 · campaign 的数字对探针的数字 可由仓库重算
图 1. campaign 那一列是 2026-08-24 这个模型两轮入库结果的均值; 探针那一列是第三、第四次标定运行的均值 —— 那是它收敛的地方。 最后一列是把探针的生成长度从 56 换成 512(也就是 campaign 自己的长度)重做一遍: 它最多再挪半个百分点,所以差异不在生成长度上,也不在服务端、流式或采样温度上。

2那三次多花的运行,以及它们换来了什么

图 1 的初次对比显示,探针在最短深度上比 campaign 落后 31 %,在最长深度上也落后 9 %。鉴于两套 harness 在 token 跨度、采样策略和传输机制上均存在差异,这一差距极易引申出看似合理的揣测。然而这些假设无一成立。

图 2 · 四次相同的运行,连着跑 可由仓库重算
图 2. 同一个容器镜像、同一个脚本,中间什么也没改。第一次运行是停掉这台机器上 其他 GPU 服务之后起的第一个容器,而且它在整整四分钟里都慢,而不是只在第一个深度上慢 —— 所以不是探针自己那次预热生成没预热到。机理这里没有确立。 确立的是量级和形状:它在第三次运行时收敛,而且伤最快的点最多 —— 这也正是为什么在有重复之前它读起来像两套 harness 的差异。
为什么这不会追溯性地损害那些 campaign 结果 campaign 的每个格子都会启动全新的独立容器,其引擎初始化过程(加载模型、编译内核、捕获计算图)在任何计时开始前便已耗时数分钟。该模型的 campaign 格子本身便执行两轮运行,两者吻合度达到 0.2 %。在另一项调换两组执行顺序的对照实验中,所得读数在 1K 上吻合至 0.3 %,在 32K 上吻合至 0.2 %;若存在如此巨大的首轮惩罚,这种高度的一致性早已荡然无存。因此,由此制定的规则仅特异性适用于冷机状态下启动的探针运行:直接舍弃首轮运行,绝不将其计入均值。

3跨越三十天的那个对照

两轮 campaign 先后相隔三十天进行,期间运行的内核版本不同,所打补丁亦有差异。其中有六组配置在两轮中均接受了实测。这六组对照数据,是判定七月的数据与八月的数据能否合并在同一张图表中的唯一依据。

图 3 · 同一个配置,隔三十天测了两次 可由仓库重算
图 3. 在两次 campaign 共有的每一个上下文深度上取平均百分比差,八月对七月。 六个里有四个落在四分之一个百分点以内。落在外面的两个没有被打发掉: 其中一个是另一项调查的主题,那项调查排除了温度、w4a16 路径和 PCIe atomics,至今没有找到原因。 一个到处都干净的对照,是一个没人认真看过的对照; 这两个恰恰是相信另外四个的理由。

4每个点都带什么,以及线画在哪

ledger 将原始测量文件投影为统一的行格式,所有数据均经由重新计算与严格校验生成,绝非人工直接编辑。每个数据点都附带两个元数据字段;若将这些信息的呈现推诿给下游绘图环节,基准测试仓库就会在无形中许诺超出其实测精度的虚假确定性。

图 4 · 每个点的 run 间极差,以及那道线的位置 可由仓库重算
图 4. 每个有多于一次 run 的 ledger 行画一个点,对数轴,因为这个分布跨了三个数量级。 这道线不是事先挑的整数:它坐在数据自己留出的空隙里。线以上的点在每张图里都用空心标记, 并在图注里点名。

2026-08-29 的 campaign 说明了元数据为何必须与测量值同行。2026-08-29 的 campaign 在单台机器上评估了八组阶梯,在连续会话中覆盖相同的十一个共有档位,每格执行两轮。三组非投机配置的 33 个档位中,越过阈值线的数量为 0,测得的最差极差为 0.59 %。与之相对,五组投机配置的 55 个档位中有多达 28 个越过阈值。这并非投机解码本身的普遍缺陷:gemma-4-31B 的投机组在每个档位上均满足评级要求,最差极差为 2.68 %。事实上,全部 28 个超标点均来自 Qwen3.8-27B,无论采用哪种注意力后端、无论是否应用补丁皆是如此。若仅汇报简单均值,这 28 个极不稳定的格子就会显得同其余 60 个一样风平浪静,进而在后续所有图表中彻底掩盖其固有的不稳定性。

5为什么报极差而不是标准差

本基准测试中几乎每个格子都仅包含两次运行。在仅有 2 个样本时,样本标准差本质上就是极差除以根号二,只是同一个数值披上了名不副实的分布外衣。唯有当样本达到 4 个时,该统计量才开始具备独立的统计学意义。正是在这一节点上,统计指标的选择变得具体可感,因为实测中恰好有一个格子记录了四次运行。

图 5 · 一个双峰格子,两个统计量,相反的结论 可由仓库重算
图 5. 这个模型 split-KV 那一组在 8K 上给出的是两个簇,而不是一个散布。 加上第三、第四次 run 让极差变宽了,这是正确的信号: 这个格子比两次 run 所暗示的更不可信。标准差往相反方向动, 因为靠近下簇多出来的一个点会让样本看起来分布得更均匀。 在这个样本量下,极差是那个无法讨好一个它并不理解的格子的统计量。

6为什么比对输出不是这里的正确性测试

验证内核改动是否无害的最直观方法,通常是比对修改前后生成的 token 序列。但在当前硬件环境下,该测试度量出的实际上是平台本身的不确定性,而非代码改动带来的影响。

图 6 · 这台机器上的 greedy 解码跨进程不可复现 可由仓库重算
图 6. greedy、温度 0、在被测那次生成之前先用同一提示同一深度预热一次, 并且一个格子的各次运行之间没有任何代码差别。它在跨进程和单进程内都会变, 而且在两种 kernel 状态之间对称,所以被测的那个改动不是原因。kernel 自身也不是: 定输入的用例在不同进程里逐位一致。变的东西在 kernel 之上、在引擎里,而它没有被定位。

本仓库中的数值结论,均在固定输入下对照 fp32 参考实现予以评估。端到端改动则基于吞吐速率以及各 worker 记录的内部执行路由进行论证。比对 token ID 的测试手段,被严格限定于已知具备确定性的计算平台;该特性在 A100 上已通过实测确立,但在当前这台机器上却并不具备。

7没有被确立的部分

第一次运行为什么慢

减速效应确有实测,但机理尚未查明。它在完成单次预热生成后依然存在,且不局限于首个上下文深度,直到第三轮运行才消除。成因究竟源于宿主机、驱动、容器还是其他组件,尚未完成归因隔离。

两套 harness 在其他模型上是否一致

标定仅采用单一模型以隔离变量。所得吻合度明确但适用范围狭窄:走其他内核路径的模型完全会因未及探讨的原因而在两套 harness 间产生分歧,其潜在成因未在此处涉及。

两个没落进带子里的对照

六组配置中有两组在两次 campaign 间产生了约 0.8 % 的漂移。其中一组排除了多项候选原因后仍未查明症结,目前仍在调查中。因此,跨 campaign 的数据合并仅能在统计区间内进行约束,不能断言二者绝对等价。

greedy 输出里变的是什么

本文并未断定任何变化的输出结果存在错误,仅说明其无法复现。TP=1 尚未测试;输出差异的源头在内核之上,但未做进一步定位。

8此后发生的变化

2026-08-26 · 第一次标定尝试才是有意思的那次 最初仅凭单次探针运行与 campaign 进行比对,测出了 31 % 的 harness 差异,且当即可给出看似合情合理的解释。随后补做的三次运行,将其转变为一种预热效应。本篇旨在阐明的核心规则,即在这里一次运行不构成一次测量;得出这一认识,正是源于当初险些发表截然相反的错误结论。
2026-08-29 · 那道线的理由被重新陈述 build_ledger.py 最初在论证 6 % 的阈值时,描述的是制定该规则时的离散分布。随后该分布发生偏移:0.27 对应的数据行入库,且双峰格子补充了两次运行,使得分布尾部变为 2.6、3.4、3.5、4.1、5.1 并跃升至 16.8,该阈值线因而仅排除了一个数据点而非两个。源码注释随后重写以描述新分布,验证器亦锁定了其尾部分布,防止后续静默失效。
2026-08-29 · 那道线又移了一次 阶梯 campaign 同日新增 88 个数据点入库,其中 55 个属于投机解码。这些点大量聚集在分布尾部:在目前超出阈值线的 29 个点中,有 28 个来自投机配置。第 29 个点则不然,它是前一天记录的双峰 8 K 格子,极差高达 16.79 %,比绝大多数投机点更为离散。前述校验门禁成功捕获了这次分布移动。当前尾部分布依次为 5.30、5.33、5.97、6.02、6.10,随后断崖式跃升至 9.50。原先的 6 % 阈值不再位于空隙中,反而在其自身与实际断裂点之间滞留了两个档位。阈值线因而调整为 8 %,恰好处于该断裂区间的中点。这一调整仅对同日测得的这两个档位重新评级,此前发表的所有结论均保持不变。
2026-08-29 · 两个间隔和一处适用范围 第 2 节原先表述为"campaign 本身每格跑两轮,吻合度达到 0.2 %"。该结论仅对本次标定所用的模型成立。实测中 Qwen3-8B 对应格子的最差离散度为 0.216 %,但这无法推广至整个 campaign:在 benchmarks/README.md 中,142 个格子中有 30 个离散度超过 1 %。该句现已明确限定为其针对的特定格子。此外,两轮 campaign 实际相隔三十天(2026-07-25 至 2026-08-24),而非五周;此前小节标题、正文及图 3 标题均误记为五周。最后,英文中的 "stated with a band" 意指统计区间,中文此前误译为"带宽陈述"(混淆了 bandwidth),现统一更正为"区间"。
2026-09-02 · attention 后端被排除在非确定性的来源之外 第 6 节指出,当前机器生成的 greedy 输出存在跨进程变动。将 W4A16 内核固定为 RDNA3W4A16LinearKernel,并对两个不稳定模型强制启用 TRITON_ATTN 后,二者依旧不稳定;而在早先判定为稳定的两个模型中,其四个格子均无任何变动。这证明注意力后端并非导致不确定性的关键变量,量化内核成为目前剩余的唯一具名候选,尚待确立(gfx1100-greedy-attn-ab/)。

自己跑一遍。全部实测数据与校验脚本均保存在仓库中:标定探针运行记录位于 benchmarks/harness-calibration/; ledger 流水线位于 ledger.jsonl 与 build_ledger.py, 若已入库的投影数据与源数据不再一致,构建脚本便会报错中止;原始不确定性日志位于 gfx1100-greedy-nondeterminism.json。 文中的每一张图表,均由 verify_doc_figures.py 基于上述源文件重新计算生成。

该不确定性问题已提交至上游议题 vllm#50603。该反馈指出了完全相同的 Triton 回退行为,但指出增加一次预热调用即可解决。鉴于本仓库的每次测量在测试前均已包含一次预热生成且依然出现输出波动,要么该修复方案不具备通用性,要么当前平台遭遇了另一处完全独立的缺陷。