05 · 基准测试与复现:测量口径与数据可信度
- 仓库:https://gitee.com/kill-life/glm5.3-flash-cybersec-sm80-vllm-deploy.git
本篇说明性能数字是如何测得、如何复现的:先给出基准测试工具与各自的适用场景,再区分两个容易混淆的吞吐口径,随后列出六条测量准则及其对应的失败案例,最后给出双来源交叉校验方法、原始记录解读方式,以及约一小时的复现流程与容差判定标准。
概览
精简修订版(严谨、句式紧凑,保留全部技术信息)
- 同配置单晚读数波动区间182–249 tok/s,核心影响因素为温度参数。六项测量规范(温度归零、≥256 token稳态窗口、满窗口预热、机器独占、长上下文三连测、样本级截断与空正文扫描)均存在带具体数值的实测反例。
- 并发日志包含两类吞吐指标:
agg_decode_tok_per_s为稳态解码窗口聚合速率;agg_total_tok_per_s为包含prefill的端到端速率。128k × 8路日志中,端到端指标显示6293 tok/s,但稳态窗口实际仅解码177个token;混淆两类口径将得出完全相反结论。 - 复现协议已纳入双源交叉校验+第三独立数据源:①客户端流式口径(输出token总数/ITL总和)、②墙钟反推口径(总量减去TTFT)、③引擎上报
metrics.speculative_decoding。客户端口径6.40,引擎口径6.425;差值≤0.4%判定一致,超出则优先核查测量口径。 - 全部结论可溯源原始数据:
bench/results/下4份JSONL文件含200余条带标签、上下文信息的原始记录。README表格由bench/render_tables.py自动生成,--check模式检测到表格与原始记录不一致时直接报错,文档内容由程序自动校验,非人工维护。 - 完整复现耗时约1小时,分为环境检查、页缓存预热、服务启动、生产准入校验、基准测试套件运行五步,与
docs/REPRODUCING.md容差判定表一一对应;偏差超限的排查方法与佐证材料已准备就绪。
1. 基准测试工具与适用场景
- 基准测试的第一条原则是:所有测量脚本都在容器内运行(整套测试工具已挂载到
/work)。理由:同一份压测脚本在容器内外运行,仅网络路径的差异就足以造成 3% 的读数偏差,而 3% 正是多个判定标准的门槛。
| 工具 | 适用场景 | 关键口径 |
|---|---|---|
| bench.py(single 与 concur) | 单流速率、并发曲线、长上下文检索测试(needle test) | 输出顶满上限、强制--ask;每个请求可指定effort与temperature |
| battery.sh | A/B 对照的固定五档,修改参数后必须使用 | 一轮约 3 分钟;内置两轮满窗口预热;档位为 single 2k 与 32k、concur 8 与 32、128k 首 token |
| run_suite.sh | 完整测试套件(六个阶段) | 约 15 分钟,包含真实的 1M 上下文档位 |
| prod_gate.py | 生产准入检查(四项) | 关键一项:28 至 32K prompt 加至少 100 输出 token 的深度解码;20K 的检查点位于触发阈值之下,无法证明任何问题 |
| topology_probe.py | 通信微基准测试 | 第 03 篇的 39 微秒与 30.6 GB/s 由此测得 |
| render_tables.py | 由 JSONL 生成 README 表格 | --check模式用于校验表格与原始记录是否一致 |
prod_gate 的四项检查并非随意设定,而是沿用同家族模型在另一代硬件上的崩溃分析结论:判断服务是否真正可用,需要同时验证以下四点:
- 越过 24K 触发阈值的深度解码
- 三路 20K 并发 prefill 的瞬时显存压力
- 重复深度解码(KV 池被使用后的状态复现)
/health接口返回 200
每项判据旁边都写有依据,脚本自身即包含必要的背景说明。
2. 易混淆的两个吞吐口径:TTFT 与 Throughput
- 并发记录中首先需要区分两个吞吐字段。
agg_decode_tok_per_s表示稳态解码窗口内的聚合速率:窗口从最早的首 token 开始,到最后一个 token 结束;窗口内的 token 数等于总输出减去请求数:每路的首 token 计入 TTFT(time to first token),不重复计入。agg_total_tok_per_s则是端到端吞吐,即(prompt 加 output)除以墙钟时间,在长上下文场景中它主要反映 prefill 吞吐。两个口径的差异不是文字游戏,下面的数值可以直接说明:
- 公式层面,bench.py 的并发打分骨架可用四行伪代码表示(变量名取自源码本意):
window=wall_clock 减去 各路最小的 TTFT ——从最早开始的那一路算起 unit=sum(输出 token)减去 请求数 ——每路首 token 计入 TTFT,不重复计入 decode=unit 除以 window ——稳态解码口径 total=(prompt 加 output 总和)除以 墙钟 ——端到端口径,长上下文时由 prefill 主导- 还有一组值得记录的读数:并发从 1 提高到 2 时,聚合速率不升反降(从 112.4 降到 91.8 tok/s),从 2 提高到 4 才回升到 165.5 tok/s。原因与 MoE 的门控机制有关:两条序列若路由到不同的专家,W4A16 的 Marlin 内核每步需要读取接近两倍的专家权重,单步耗时从 17.5 毫秒量级上升到 43 毫秒量级。这不是缺陷,而是 MoE 架构决定的成本。
3. 六条测量准则与对应的失败案例
- 以下六条测量准则均对应真实实测失败案例,而非形式化检查清单,各准则的实测现象、成因与纠正措施如下:
| # | 准则 | 实测现象 | 原因与纠正措施 |
|---|---|---|---|
| 一 | temperature 强制设为 0 | 服务端默认采样温度为 0.3,同一配置 32k 档读数在 182–249 tok/s 间波动,MTP 接受长度逐轮不同;清空采样参数、退回权重默认值 1.0 时波动进一步扩大 | 显式传入--temperature 0,确保每次测量均携带该参数 |
| 二 | 输出顶满 256 token 稳态窗口 | 默认检索型请求仅十几个 token 即结束,SSE 分块导致 63 被误读为 106;另有 3 条记录已废弃,仅作历史数据留存 | 通过--ask强制长输出,或显式设置输出上限为 256 |
| 三 | 预热且覆盖完整窗口 | 首个请求触发 JIT 编译,首档速率从 11 tok/s 降至 52;深度提升后,预热 32 个输出 token 仍无法抹平差异,三次复测结果为 207–217 | 保留battery.sh内置的两轮满窗口预热机制,不得删减 |
| 四 | 测量期间独占机器 | 邻实例加载权重时,单 worker 占用 12 核以上,8 进程可占满 112 核;本机步时从 19.6 ms 升至 78 ms,差异约 4 倍 | 先用nvidia-smi自查资源,与同机其他使用者约定错峰运行 |
| 五 | 长上下文结论需连测三次 | 1M 首 token 因单次 417 秒的离群读数,被误判为“慢三成四”;三次复测确认长期值为 312 秒 | 三次复测为必要步骤,非可选项 |
| 六 | 逐样本检查截断与空正文,不唯均值论 | 330 格采样中 6 格触发 4400 token 输出上限,其中 1 格正文完全为空(预算被思考链耗尽);该格事实命中为 0,将单档均值从 0.983 拉低至 0.917,导出错误结论;上限提至 7000 重测后,该档均值回到 1.000,原结论不成立 | 输出预算为「思考+正文」共享,思考型模型易耗尽预算;跑完先检查finish_reason=length与空正文计数,bench/sampling_sweep.py已内置该告警 |
六条准则说明:前五条来自性能测量实践,唯有准则六由本套件自身的结论纠错反推得出——单个空正文样本即可导致整档参数误判。其普适性结论为:均值不能替代逐样本检查,尤其当失败样本为极值时(空正文命中率恒为 0,恰好是分布的下界)。
准则四补充说明:8 个加载进程占满 112 核只是问题的一部分。并发加载会同时破坏「双实例对照」的两个前提:对照组与实验组均处于不稳定状态,测得的差异无法归因。仓库通过实验驱动器的文件锁机制应对:加载权重时持有独占锁,测量时持有共享锁,保证同一时刻仅一个实例执行对应操作。该机制虽看似繁琐,但已在实际使用中两次避免数据污染。
4. 三来源交叉校验机制
本套件已将三来源交叉校验写入复现协议,读数接近时须通过独立来源交叉验证,不依赖单一脚本:
- 来源A:客户端流式测量:累计输出token数除以流内间隔之和,天然排除首token等待时间,直接近似流式观感速率。
- 来源B:墙钟反推:输出token数除以(总时长-首token时间),为客户端流式的独立第二来源;实测与来源A偏差小于1%。
- 来源C:引擎自报指标:响应体中
metrics.speculative_decoding(由SPEC_DECODE_METRICS=summary开启),与前两者相互独立,包含接受长度、草稿命中率、每步分布三类指标。
三者不一致时按固定顺序排查:先确认口径是否对应同一窗口(稳态窗口/端到端),再检查首token是否按每路一次扣除,最后排查物理层问题。引擎与客户端间0.4%的残差来自记账口径(保底校正项),为固定系统偏差,非故障。
5. 结果记录解读
bench/results/下4份基线JSONL文件各司其职:MTP深度6定版口径、调优全量记录、部署形态二(TP=4×PP=1)的1M与并发prefill历史记录、三卡配置时期基线。
单条原始记录示例:
{"label":"decode_2048_r1","effort":"low","prompt_tokens":1862,"output_tokens":256,"ttft_s":0.382,"steps":41,"step_ms":25.57,"accept_len":6.24,"decode_s":1.02,"output_tok_per_s":250.27,"needle_code":"831EAF2F"}核心字段含义:
| 字段 | 含义 |
|---|---|
| accept_len 6.24 | 单解码步平均净增约5.24 token(接受长度6.24减1) |
| step_ms 25.57 | MTP深度6下单步耗时,与理论值25.66 ms基本吻合 |
| steps 41 | 该请求引擎总步数;accept_len=输出token数÷步数(256÷41=6.24) |
| output_tok_per_s 250.27 | 2k高可预测文本档单流速率;普通散文结果单独统计 |
| needle_code | 随机ORACLE校验码,用于确认长上下文响应来源 |
| answer_head | 输出前数十字符切片,用于人工校验输出有效性 |
几组代表性读数:
- 1M首token三次复测:311.8~312.6 秒
- 128k八路并发端到端:两次复测6292、6293 tok/s(该口径由prefill主导)
- 普通散文场景:85~91 tok/s
- 32路并发稳态窗口聚合速率:683.1 tok/s
所有超出容差的记录均附专门解释,越界场景配套后续处理指引。
5.1 分位读数说明:p50与p90
并发记录除聚合速率外,还包含单路输出速率分布、首token p50/p90分位数两组数据:分布数据反映并发提升后单路速率的衰减程度,分位数反映prefill排队时间的中位与高位差异。
两个核心读数逻辑:
- 排队公平性:p90/p50比值越接近1,各请求等待时间越均衡;比值严重失衡时,尾部请求承受数倍等待,表现为偶发卡顿而非平均速率下降,排查方向不同。
- 对照阅读原则:聚合值受长尾拉伸,分布值反映单请求真实表现,二者缺一易遗漏问题。记录旁注「看公平性(并发拉高后单流掉多少)」是将该读法写入元数据的实践。
6. 一小时复现流程与容差判定
完整复现共五步,含服务启动总耗时约60分钟;可将预热与测试准备并行以压缩时长:
./setup.sh--check# 0分钟,只读环境检查./warm_cache.sh# 3分钟,页缓存已热则立即返回./serve.sh&&./wait_ready.sh# 合计约6分钟,含一次启动makegate# 四项准入检查全部通过后方可继续cdbench&&./battery.sh repro# 运行一轮复现基准测试并写入结果测得数据需与docs/REPRODUCING.md容差判定表比对,摘录示例如下:
| 指标 | 基准值 | 容差 | 越界优先排查项 |
|---|---|---|---|
| 单流2k | 250.3、256.1 | ±5% | temperature设置、预热是否充分 |
| 32路并发窗口聚合 | 683.1 | ±10% | 32路是否跑满、同机是否有其他实例加载权重 |
| 1M首token | 312 秒 | ±10% | 必须连续测三次,单次读数无效 |
差异报告需满足标准流程:提交环境指纹原文、复现命令原文、原始记录、差异最大档位的引擎日志、机器独占性说明,五项齐全才予受理。仅报速率值、无口径/环境/原始数据的报告无法处理。
6.1 复现失败需提交的五项材料
docs/REPRODUCING.md规定,复现失败需提交五项材料,从问题定位角度各有不可替代的作用,共同支撑完整归因:
优先级按排列顺序递减:缺少环境指纹则差异无法归因;缺少复现命令则复现无法开展;缺少原始记录则读数无依据;缺少日志则故障过程无法还原;缺少独占性证明则计时结果可能受干扰。将该图与容差表配合使用,可显著提升问题报告质量。
7. 数据记录规范
- 标签四级命名:按「实验-配置-档位-轮次」命名标签,自解释字符串支持多年后检索仍可还原完整实验过程。
- 双轮记录原则:同一配置至少两轮同日数据;推翻已有结论必须有第三个独立数据点支撑。
- 保留历史异常:历史疑点数据连同原因一并留存(如预热假象期的低接受长度记录);数据会过时,但缺失记录会引发新问题。
- 表格程序生成:README表格仅可由原始数据通过公式生成,手工修改生成区会触发lint报错;以程序校验替代人工维护,每次检查自动执行。
最终结论以数据为核心:复现基准测试完成后,将结果首行附于评审中,所有测量准则与记录规范的价值即会体现——结论直接由数据支撑,无需额外解释。