benchmark 变快的归因:路径证据与分段计时
在适配工作里,改动落地之后 benchmark 数字变好,这个数字常被直接记成那处改动生效。数字变好只是观测结果,把它归因到某处改动需要额外证据:命中路径是否真的改变、收益落在哪一段、收益是否被新增开销抵消。
固定工况:四类「变快」来源
同一个变快至少来自四类,形态一致,须先分开。
| 来源 | 典型成因 | 固定动作 |
|---|---|---|
| 环境差异 | 换机器、换相邻节点、换驱动、换基础软件栈版本 | 固定机器与节点:同 NUMA 域、同卡位、同驱动版本;基础软件栈钉在 <pinned-version> |
| 测量误差 | 预热不足、缓存效应、抖动噪声 | 充分预热,丢弃前 N 次迭代;固定复测次数,取中位数并去掉首尾各一次 |
| 负载漂移 | 请求集不同、输入与输出长度分布变化、并发变化 | 固定请求集与随机种子:固定 input_len / output_len 分布与 seed,记录 --max-num-seqs |
| 改动本身 | 目标算子路径被替换 | 需要路径证据与分段计时,见下文 |
压测入口把工况写进命令:
# 固定工况的压测入口(字段名示意)
python -m vllm.benchmarks.benchmark_serving \
--model <model-path> \
--dataset-name random \
--random-input-len 1024 --random-output-len 256 \
--random-range-ratio 0.0 \
--num-prompts 512 \
--seed 1234 \
--max-num-seqs 64
路径证据:把变快接到改动上
两个字段决定归因是否成立。target_backend 是打算让它走的路径,resolved_backend 是它实际命中的路径。常见问题是指定了目标路径却未命中:自动降级或 guard 失格会让实际路径停在通用实现上。
只有 resolved_backend 相对基线发生变化、且热点随之移动,收益才有资格归到那处改动上。resolved_backend 未变而 benchmark 变快,收益来自别处。
# 固定路径并保留命中结果(字段名示意)
export ****_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
source /usr/local/****/set_env.sh
python -m vllm.entrypoints.openai.api_server \
--model <model-path> \
--attention-backend FLASH_ATTN \
--enforce-eager
在 **** 的 ****(8 卡,单卡 64GB HBM,卡间互联 392 GB/s)上,改动前后两组数据须在同一 NUMA 域、同一卡位取得,并逐次比对启动日志里的后端选择结果。
分段错配:端到端均值会把错配抹平
推理分两段。一项优化常只落在一段:prefill 吃到收益、decode 未兑现,或反过来。端到端一个均值会把两段差异抹平,带偏整体结论。
| 指标 | 覆盖的段 | 说明 |
|---|---|---|
| TTFT | prefill + 首次解码 | 反映提示处理与首 token 延迟 |
| TPOT / ITL | decode | 相邻输出 token 间隔 |
| 端到端吞吐 | 两段叠加 | 单独看会掩盖分段错配 |
收益被额外开销抵消
功能已开启、收益却不成立,常见原因是新增的调度、拷贝、同步把收益吃掉:
- 额外的 H2D / D2H 拷贝:为绕开某条路径引入的主机往返;
- kernel launch 开销:算子更碎、下发更密;
- 同步点增多:每个 micro-batch 强制同步。
两种结论要分开记:收益为零(优化没碰到瓶颈)与收益被抵消(收益存在但被新增开销吃掉)。处置方向不同;同时写明结论在哪种负载下不成立(短请求、长请求、混合)。
热点归因:靠设备利用率形态区分
即便路径变了,仍要回答瓶颈是否被改动触及;设备利用率形态是可观测判据。
| 利用率形态 | 归因方向 | 处置 |
|---|---|---|
| 持续高位但仍慢 | 设备在跑低效 kernel,瓶颈在被改动的算子路径 | 改 kernel 或换后端 |
| 时高时低、间歇空转 | 瓶颈在主机侧的下发或同步链路 | 合并算子、减少下发与同步 |
定位步骤
- 固定工况:同机、同卡位、同驱动,预热后丢弃前 N 次迭代,固定请求集与
seed。 - 核对路径:比对
target_backend与resolved_backend,确认是否命中目标路径。 - 分段计时:分别取 TTFT 与 TPOT / ITL,对照 prefill 段与 decode 段。
- 估算开销:量出新增拷贝、launch、同步的耗时,判断是否抵消。
- 判热点:看设备利用率形态,判瓶颈在设备侧还是主机侧。
- 收尾:写明结论在何种负载下成立。
记录字段
# 一条归因记录(字段名示意)
stack_fingerprint:
base_stack_version: # 基础软件栈,写 <pinned-version>
driver_version:
hardware_sku: # 卡型(8 卡,单卡 64GB HBM,互联 392 GB/s)
node: # 机器、节点、NUMA 域、卡位
workload:
model_name:
input_len: # 固定分布
output_len: # 固定分布
seed:
max_num_seqs:
warmup_iters: # 丢弃的预热迭代数
repeat_count: # 复测次数与取值(中位数 / 去首尾)
path:
target_backend:
resolved_backend:
changed: # 路径是否相对基线变化
perf:
ttft: # prefill 段
tpot: # decode 段
e2e_throughput:
overhead:
extra_copy: # 新增 H2D / D2H 拷贝
kernel_launch:
extra_sync:
hotspot:
device_util_trace: # 持续高位 / 时高时低
hotspot_stage: # 热点落在哪一段
status: # 收益成立 / 收益为零 / 收益被抵消
小结
benchmark 变快本身不构成归因。判定一处改动生效至少要三项证据:固定工况下的复测、resolved_backend 相对基线的变化、按 TTFT 与 TPOT 分开的分段结果。三项不齐时,结论记为收益不成立,并写明成因(路径未变、被额外开销抵消、或瓶颈不在此段),以便下次按记录复现。