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 间隔
端到端吞吐 两段叠加 单独看会掩盖分段错配

收益被额外开销抵消

功能已开启、收益却不成立,常见原因是新增的调度、拷贝、同步把收益吃掉:

两种结论要分开记:收益为零(优化没碰到瓶颈)与收益被抵消(收益存在但被新增开销吃掉)。处置方向不同;同时写明结论在哪种负载下不成立(短请求、长请求、混合)。

热点归因:靠设备利用率形态区分

即便路径变了,仍要回答瓶颈是否被改动触及;设备利用率形态是可观测判据。

利用率形态 归因方向 处置
持续高位但仍慢 设备在跑低效 kernel,瓶颈在被改动的算子路径 改 kernel 或换后端
时高时低、间歇空转 瓶颈在主机侧的下发或同步链路 合并算子、减少下发与同步

定位步骤

  1. 固定工况:同机、同卡位、同驱动,预热后丢弃前 N 次迭代,固定请求集与 seed。
  2. 核对路径:比对 target_backend 与 resolved_backend,确认是否命中目标路径。
  3. 分段计时:分别取 TTFT 与 TPOT / ITL,对照 prefill 段与 decode 段。
  4. 估算开销:量出新增拷贝、launch、同步的耗时,判断是否抵消。
  5. 判热点:看设备利用率形态,判瓶颈在设备侧还是主机侧。
  6. 收尾:写明结论在何种负载下成立。

记录字段

# 一条归因记录(字段名示意)
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 分开的分段结果。三项不齐时,结论记为收益不成立,并写明成因(路径未变、被额外开销抵消、或瓶颈不在此段),以便下次按记录复现。