习慈羊xiciyang
联系
订阅
正在读取订阅状态…

调优中的统计决策:为什么 3% 的阈值不够,以及那 3 次"重复测量"其实不够用

你改了一个参数,重新压测。吞吐从基线的某个值变成了 +3.5%。上一轮改另一个参数是 +3.1%。这两个配置,哪个该留下?

默认做法是定一个阈值,比如 3%,超过就留。但如果你知道这台机器的测量标准差大约是 2%,那么这 0.4% 的差别比噪声还小——这两个数字之间没有任何可判定的差异。你以为你在区分两个配置,其实你在读两次噪声。

性能调优里最容易被跳过的一步,是回答”这次判定凭什么成立”,而不是”调哪个参数”;先说判定为什么容易不成立,再给四层错误与对应的四件工具——当信噪比接近 1 时,固定阈值和固定重复次数都只是感觉。

第一层:把阈值定成常数,等于假设噪声是常数

固定阈值 3% 的隐含假设是:这台机器的测量噪声不随时间、不随配置变化。

这个假设几乎总是错的。同一台机器上,噪声至少受这些因素影响:显存碎片程度、散热与功耗状态、是否有邻居进程、缓存命中率、以及当前配置本身(并发越高,抖动往往越大)。

正确的形式是把阈值和噪声挂钩:

t = max(2 × σ_baseline, 3%)

读作:接受一个变更,至少要求它的改善量达到基线噪声的两倍;同时保留 3% 的下限,避免在一台异常安静的机器上把门槛降到没有意义。

这个改动看起来很小,但它带来一个必须付的代价:σ_baseline 不能再从手册或经验里拿,必须在本机实测。

我在一台 8 卡机器上标定过这件事,得到的决策阈值是 3.8%。按上面的公式反推,对应的 σ_baseline ≈ 1.9%——和我对这类机器的直觉一致。也就是说,在那台机器上,3% 的阈值是被噪声吃掉的:任何 3% 上下的”改善”都无法与抖动区分。

标定本身不复杂:同一份配置,重复跑若干轮,取吞吐的标准差。但它必须和压测条件一起记录(并发、请求量、输入输出长度分布),因为 σ 不是硬件常数,它是”这台机器在当前负载下的噪声”。

附带的一个判据

σ_baseline 本身就是一个体检指标:

如果 σ_baseline > 5%,先怀疑压测环境:散热不足、有干扰进程、工具链不稳,或者测法本身不对——这不是”调优难”。

此时正确的动作是停下来修环境,而不是把阈值调高去”适应”一个坏掉的环境。把噪声当成需要克服的困难,会让后面所有结论都建立在一个不可重复的基线上。

第二层:“跑了 3 次没看出差别”——这句判断可能没有内容

这是我认为最值得单独讲的一层,因为它违反的是很多人的直觉。

我原来的做法是”同配置重复 3 次”。3 次听起来挺谨慎。但假设检验对样本量是有要求的,给定:

  • 噪声 σ(实测)
  • 你希望可靠检测出的效应量 d
  • 显著性水平 α = 0.05,功效 1 − β = 0.8

单尾双样本所需的重复次数大致是 [1]:

n ≈ (z_α + z_β)² · 2σ² / d²

代入 σ = 2%、d = 3%、z_0.05 = 1.645、z_0.2 ≈ 0.8416:

n ≈ (1.645 + 0.8416)² × 2 × 0.02² / 0.03²
  ≈ 6.18 × 0.0008 / 0.0009
  ≈ 5.5  →  6 次

要可靠发现 3% 的效应,每组需要大约 6 次重复。而我只跑 3 次。

那 3 次能换来什么?把公式反解,在 n=3 的预算下,能可靠发现的最小效应量是:

d ≈ √( (z_α + z_β)² · 2σ² / n )
  ≈ √( 6.18 × 0.0008 / 3 )
  ≈ 4.1%

所以”跑 3 次”这份预算的真实含义是:

我最多只能以 80% 的功效发现 ≥ 4.1% 的真实改善。低于这个幅度的差异,无论我看没看见,都不构成证据。

重复次数与可检测的最小效应量:跑 3 次只能发现 ≥4.1%,想发现 3% 需要约 6 次

这意味着两件事:

  1. “跑了 3 次没看出差别”绝不等于”没有差别”。它只等于”没有 ≥4.1% 的差别”。
  2. 更重要的:你不该把结论建立在一个没算过的样本量上。原来的我把”多跑几轮”当成谨慎,其实那只是把一个统计问题藏进了手感里。

正确的做法是把这件事写在报告里,叫做本轮灵敏度声明:

本轮 σ=2.0%,重复 n=3,因此本轮只能以 80% 功效发现 ≥4.1% 的真实效应;更小的效应判定为”无结论”,不是”无改善”。

如果预算不够,专业做法是主动下调声明:承认这一轮只具备发现大效应的灵敏度,把”3% 的改善”标成无结论,等预算允许时再补测。

第三层:边看边停,本身就是多重比较

固定样本检验有一个前提:样本量在开测之前就定好了。

而调优的真实动线是”边看边停”——看到结果好就想收工。问题在于,停下来的时机是数据决定的。这会显著放大假阳性:你反复偷看,第一次看到 p < 0.05 就停,那么这个 0.05 已经不是那个 0.05 了。

举个例子说明这个偏差有多自然:抛 10 次硬币,看到”7 正 3 反”就停下来说”这枚硬币偏向正面”——这就是可选的停止规则造成的假象。调优里同样的机制在悄悄工作,只是你看不见它。

解决办法是把检验换成 always-valid 的构造 [2](例如基于 confidence sequence 的 always-valid p-value,或混合序贯概率比检验 mSPRT)。它的性质正是为这种动线设计的:

在任意时刻停下来做判断,总的第一类错误率都不超过 α。

代价要说清楚:always-valid 不减少所需的样本量,它保证的是”随时可停仍然合法”,不是”可以少测几次”。这两件事经常被混为一谈。

第四层:五个指标一起看,犯错概率会膨胀

调优从来不是只看一个数。吞吐、首字延迟、单 token 时间、成本、质量分——至少五个 KPI。

如果对每个 KPI 各自用 α = 0.05 判一次,那么”至少有一个误判为显著”的概率会随指标数上升。五个指标下,即使所有变更都是无效的,出现至少一次假阳性的概率也远高于 5%。这不是数学细节,这是”我明明每次都判对了,为什么整体还是在赌”的根源。

做法是用 Benjamini-Hochberg 控制错误发现率 [3]:把各 KPI 的 always-valid p 值排序,拒绝满足 p_(i) ≤ α · i/m 的假设(m 为比较数)。

但真正让我觉得这个设计值得抄下来的,是它多加的那一条:

同时被多个 KPI 拒绝的”候选效应”,才进入决策表。

注意方向——它让接受变得更难,不是更容易。常见的错误做法是”任一指标显著改善即认定有效”,那是在放松标准;而这个设计要求一个效应在多个 KPI 上同时成立。它把多重比较修正从”技术补丁”变成了决策纪律。

贯穿线:这四层错误其实是同一句话

四层拆开看是四件事,合起来是一句话:

它们都在回答同一个问题——“这次判定凭什么成立”;而它们都失败于同一个原因:把一件需要被测量的东西,当成了可以被设定的东西。

  • 阈值需要被测量(σ),却被设定成了 3%;
  • 样本量需要被计算(功效分析),却被设定成了”跑 3 次”;
  • 停止时点需要被控制(always-valid),却被放任成了”看着差不多就停”;
  • 判定个数需要被修正(FDR),却被忽略成了”各判各的”。

所以这套东西的核心,是把四个原本靠感觉的旋钮换成四个由数据决定的量。统计协议在这里的作用,是让”接受”和”拒绝”都成为一个可以被别人复算的决定。

这解释了为什么接下来的闸门顺序、终止条件、漂移检测都必须跟着改:一旦阈值是算出来的,判定的次序就变成了下一个决定性变量——前一道不过,后一道的问题就没有意义。

闸门顺序不能乱

有了判定协议,还要规定判定之间的次序。

调优变更要依次通过六道闸门

我采用的闸门顺序是:

  1. 稳定性闸:成功率 < 99% → 立即回滚;
  2. 质量闸:质量指标劣化超过 0.5% → 回滚;
  3. SLA 闸:任一红线越界 → 回滚,并永久跳过这个方向;
  4. 资源闸:显存越过硬上限 → 回滚;
  5. 统计闸:always-valid p 值未过 → 走”无显著变化”路径;
  6. 多目标组合决策。

顺序是刻意的,不是顺手排的:

  • 稳定性和质量排在统计之前,因为一个成功率只有 95% 的配置,它的吞吐数字根本不值得做统计比较。先回滚,再讨论它快不快。
  • SLA 闸越界要”永久跳过这个方向”,而不只是回滚这一次。这是防止优化器在同一个方向上反复试探一条已经被判定不可接受的路。
  • 统计闸排在最后,因为只有前面几道都过了,“这个改善是否显著”才成为有意义的问题。

一个中间态:ACCEPT-MARKED

真实决策里经常出现”拿延迟换吞吐”的取舍——吞吐显著上升,但延迟也在变差,只是还没越界。

硬判”接受”或”拒绝”都会丢信息。我用的做法是引入一个中间态:

ΔT ≥ t 且延迟劣化落在 5%–10% 区间 → ACCEPT-MARKED,2 轮后复评。若后续 2 轮无新增收益则自动回退。

这在统计上叫非劣效的思路:在”没有显著更差”的前提下,换来别的好处。它的价值在于让”有条件的接受”变成一个有到期时间的状态,而不是一个靠人记住的口头约定。

什么时候该停

没有终止条件的优化循环,会一直跑下去,而且每一轮都能找到”看起来有改善”的配置——因为总有噪声。

我的终止条件是四个,满足任一即收敛:

  • 连续 ≥3 轮没有 ACCEPT,且可探索方向已穷尽;
  • 预算耗尽(轮数上限);
  • SLA 或资源饱和(延迟余量 <10% / 资源触顶 / 偏好达成余量 >30%);
  • 漂移冻结 → 停机待人工介入(这条比较特殊,见下节)。

另外两条直接停机:连续 2 次启动失败;检测到环境漂移。它们需要人介入,不应该被混进”调优完成”的结论里。

还有一个容易被忽略的记账细节:

REJECT 默认不留痕;同一个参数累计 3 次被拒,才标记为”已耗尽”。

为什么值得这么设计?因为在噪声环境下,一个方向被拒一次可能只是运气。如果第一次拒绝就把这个方向永久划掉,你会系统性地过早收窄搜索空间——拒一次就永久淘汰,等于让噪声替你做了搜索决策。

何时该重新调:把漂移检测算法化

调优不是一次性动作。服务在跑,流量在变,环境在漂移。所以真正的问题是:什么时候该重新调?

用规则式判据(比如”输入长度的 P99 偏移超过 30% 就重调”)不可靠,因为阈值同样是拍出来的、而且它对缓慢漂移不敏感——一个每月涨 3% 的趋势,永远碰不到 30% 的墙,但一年后它已经偏离到另一个世界了。

把这部分算法化,可选:

  • CUSUM / Page-Hinkley:检测均值漂移,适合”某个指标整体抬升/下移了”;
  • ADWIN:自适应滑动窗,检测分布变化,轻量且鲁棒,我把它作为默认 [4];
  • BOCPD(贝叶斯在线变点检测):给出变化点的后验概率,成本高,留给关键指标(成本、SLA)[4]。

它们的共同优势不只是”能报警”,而是能回答”变化发生在哪一刻”。这个信息对定位原因很关键:知道变化点,你才能去查那一刻发生了什么(上线了新版?流量结构变了?换了机器?)。

一个真实的坑:配置模板会和标定值脱钩

讲一个我在自己工程件上踩到的例子,它比任何原则都更能说明”为什么这件事必须写成流程”。

前面说过,我在现场标定出的决策阈值是 3.8%,并在操作手册里多处引用了它。但同一份手册里的配置模板,默认值写的是:

{ "sigma_throughput": 0, "decision_threshold_t": 0.03 }

0.03 和标定出来的 0.038 不一致,sigma_throughput 干脆是 0——按公式 t = max(2σ, 3%),σ = 0 会推出 t = 3%,正好是那个被噪声吃掉的旧值。

照模板走的人会算错门槛,而且不会报错。

这不是粗心,这是”同一件事有两份口径”的必然结果:一份在标定记录里(3.8%),一份在模板默认值里(3%),而人在赶时间的时候会信模板。它和上面讲的统计方法都无关——它是流程问题。

修正方式很直接:让模板不携带可推断的默认值,而是从标定产物里读。凡是”必须从实测得来”的数字,就不该在模板里给一个看起来合理的默认值——那个默认值迟早会被当成真值使用。

这套协议不回答什么

必须说清楚边界,否则上面这些会显得比它实际能做的更多:

  1. 它不回答”参数空间里还有没有更好的点”。那是搜索策略的问题(采样、代理模型、采集函数、早停)。统计协议只回答”这一次判定是否成立”。
  2. 它不减少所需样本量。 always-valid 推断让”随时可停”合法,不让你少测。效应量贴近阈值时,预算仍然可能不够。
  3. 它不能诊断坏掉的环境。 σ_baseline > 5% 这条判据能告诉你”环境有问题”,但查不出是散热、干扰还是工具链——那需要单独的排查。
  4. 它依赖 σ 的正确标定。如果 σ 本身是在一个不稳定的环境里测出来的,整条链的阈值都会偏。这也是为什么 σ 必须和压测条件一起记录。
  5. 它对”多目标”的处理有前提。加权得分法和 Pareto 方法都假设目标数不多(我采用的上限是 5 个)。目标再多,必须先做聚合或分层,否则权重本身就没有意义。

回到开头那个问题:+3.5% 和 +3.1% 哪个留下?

按这套协议,答案不是”3.5% 因为更大”,而是:

先看 σ。如果 σ ≈ 2%,那么两个都不显著——这一轮的正确结论是”无显著变化”,而不是”3.5% 更好”。

这个答案让一次调优”白跑了”,听起来是坏消息。但相比把噪声写进配置、然后再花两轮去调一个从未真实存在过的改善,它是更便宜的那条路。

调优里最贵的东西不是算力,是”你以为你测到的”。

参考文献

[1] Cohen, J. (1988). Statistical Power Analysis for the Behavioral Sciences(第 2 版)—— 样本量公式 n ≈ (z_α+z_β)²·2σ²/d² 的标准出处。

[2] Howard, S. R., Ramdas, A., McAuliffe, J., & Sekhon, J. (2021). Time-uniform, nonparametric, nonasymptotic confidence sequences. arXiv:1810.08240:https://arxiv.org/abs/1810.08240(2026-10-11 实测可达)—— always-valid 推断;mSPRT 出自 Robbins (1970) 的序贯检验工作。

[3] Benjamini, Y., & Hochberg, Y. (1995). Controlling the False Discovery Rate: A Practical and Powerful Approach to Multiple Testing. JRSS-B. DOI: 10.1111/j.2517-6161.1995.tb02031.x

[4] 漂移检测的两篇原始文献:Bifet, A., & Gavaldà, R. (2007). Learning from Time-Changing Data with Adaptive Windowing(ADWIN);Adams, R. P., & MacKay, D. J. C. (2007). Bayesian Online Changepoint Detection,arXiv:0710.3742:https://arxiv.org/abs/0710.3742(2026-10-11 实测可达)。

关于数据的核验说明:σ≈2%、标定出的 t = 3.8%、以及第二节那组样本量算术,都是我在一台 8 卡机器上实测与推算得到的,原始记录不在公开位置。可替代的核验路径是:公式与推导是公开的 [1][2][3],读者用自己机器的 σ 代入即可复算;而”配置模板默认值 drift 成了 3%、与标定的 3.8% 不一致”这一条,属流程观察,任何有配置模板的团队都可自查。真正可迁移的是那四个”由数据决定”的量,不是具体数值。

评论

填个昵称就能发,不需要注册或登录