如何用 --bm_modeadaptive 运行 Folly 基准测试以获得噪声环境下的公平比较【免费下载链接】follyAn open-source C library developed and used at Facebook.项目地址: https://gitcode.com/GitHub_Trending/fol/folly传统基准测试方式是逐个把每个 benchmark 跑完再报告最小耗时这在安静的系统上没问题但在噪声较大的 VM 上会失效benchmark A 可能正好落在系统变慢的时段B 落在变快的时段两者的相对性能就被扭曲了。Folly 的folly/Benchmark.h框架提供了--bm_modeadaptive运行模式它把所有 benchmark 的短采样片以随机顺序交叉执行让同一次运行中的每个 benchmark 看到相同的系统状态并持续采样直到结果同时满足稳定和精确两个条件。本文说明如何在噪声环境下用该模式跑出一组可以相互公平比较的测量结果以及如何判断结果是否可信。先准备一个可运行的 Folly 基准测试adaptive 模式作用于标准的folly/Benchmark.hbenchmark 二进制。按 docs/Benchmark.md 中的示例最简结构是#include folly/Benchmark.h #include folly/init/Init.h #include vector using namespace std; using namespace folly; BENCHMARK(insertFrontVector) { // Lets insert 100 elements at the front of a vector vectorint v; for (unsigned int i 0; i 100; i) { v.insert(v.begin(), i); } } BENCHMARK(insertBackVector) { // Lets insert 100 elements at the back of a vector vectorint v; for (unsigned int i 0; i 100; i) { v.insert(v.end(), i); } } int main(int argc, char** argv) { Init init(argc, argv); runBenchmarks(); }两点文档明确提到的前提该框架目前只面向单线程测试内部可以做 fork-join 并行并测量总运行时间。计时使用clock_gettime的CLOCK_REALTIME时钟文档要求使用较新的 Linux 内核2.6.38 或更新否则CLOCK_REALTIME的分辨率不足。不传--bm_mode时框架使用默认值best-of定义见 Benchmark.cpp此时二进制会打印提示建议使用更快、更鲁棒的--bm_modeadaptive。用 adaptive 模式运行基准测试按 docs/BenchmarkAdaptive.md 的快速开始主路径命令为buck2 run //mode/opt //your:benchmark -- --bm_modeadaptive其中//your:benchmark是文档中的占位符需要替换为你自己的 benchmark 构建目标--之后的参数--bm_mode等传给 benchmark 进程本身。在安静系统上用默认选项就能较快收敛。在噪声较大的 VM 上文档建议加大每个 benchmark 的超时buck2 run //mode/opt //your:benchmark -- --bm_modeadaptive --bm_max_secs30--bm_max_secs的 gflag 帮助文本给出的建议是 20–30 秒以获得鲁棒结果默认值 1 秒只适合快速迭代。加--bm_verbose可以看到采样轮次、收敛进度等底层统计便于判断运行状态。运行逻辑上adaptive 模式按以下循环工作文档Algorithm overview一节while not converged: measure baseline (every 8 rounds) measure suspender baseline (every 2 rounds) for each benchmark (random order): measure calibrated iterations, record sample, recalibrate check convergence every 150ms每个 benchmark 从iterCount1起步每采样一次后自行调整迭代数使每个测量切片时长约等于--bm_slice_usec默认 1ms避免单独的校准阶段受冷启动影响。关键参数与默认值下表汇总与 adaptive 模式相关的主要参数默认值取自 Benchmark.cpp 中的 gflag 定义用途说明以该文件帮助文本和 BenchmarkAdaptive.md 为准参数默认值用途与适用条件--bm_modebest-ofbest-of或adaptive。adaptive 交叉采样并运行到目标分位数估计既稳定又精确--bm_max_secs1每个 benchmark 的最大秒数。adaptive 模式下建议 20–301 秒默认值面向快速迭代--bm_target_precision_pct0.4收敛精度目标目标分位数估计的 95% 置信区间宽度须小于估计值的该百分比0.4 表示 100ns 的估计需 CI 小于 0.4ns。更紧的值如 0.1需要更长的--bm_max_secs或更安静的系统。接近零时由 20ps 绝对下限取代相对精度--bm_min_secs0.1每个 benchmark 收敛前至少运行的秒数用于用更长时间平均掉系统抖动以更高置信度换取速度--bm_min_samples20每个 benchmark 收敛前的最少采样数--bm_target_percentile33.3报告每切片迭代时长的哪个分位数。33.3 近似好运行的中位数关注尾延迟时可用 90--bm_slice_usec1000每个连续测量切片的微秒时长。低于 1000 有 harness 干扰影响结果的风险--bm_verbosefalse打印诊断细节adaptive 模式下为收敛进度与 baseline 统计选择--bm_target_percentile时注意文档给出的理由p0最小值偏乐观可能掩盖系统争用导致的代码问题p50 会被瞬时变慢拉偏p33 尝试成为好运行的中位数。如果你的代码存在快慢双峰分布低分位数可能隐藏慢路径需要尾延迟时改用--bm_target_percentile90等更高值。判断收敛如何读取运行结果adaptive 模式对每个 benchmark 同时检查三项条件全部通过才算完成文档Are we done?达到最少采样数与最短运行时间稳定性按时间把样本一分为二各自计算分位数估计与置信区间要求前半估计落在后半区间内、且后半估计落在前半区间内精度置信区间宽度不超过 max(相对精度目标, 20ps 下限)。超时未收敛时框架报告的是不完整运行而不是收敛结果。文档示例的稳定性判定如下注意这是文档示例不是每次运行都会出现的固定数值采样 200 次后前半 p33 4.2ns ± 0.1ns后半 p33 4.3ns ± 0.15ns因每个估计都落在另一方的区间内判为稳定。结果输出由 BenchmarkAdaptive.cpp 生成未满足条件的 benchmark 会在统计中标注[unstable]达到--bm_max_secs上限时出现Exceeded max_secs (unstable)一类的提示并列出各 benchmark 的收敛状态Converged / Exceeded max_secs 等分组。想核对具体进度时加--bm_verbose它会持续打印采样轮次与收敛进展。需要牢记文档的提醒稳定 ≠ 准确。稳定的测量也可能测到错的数二进制布局差异、贯穿整次运行的热降频等都会造成但不稳定的测量一定不可信。遇到持续 [unstable] 警告时怎么处理如果看到某个 benchmark 一直振荡、迟迟不收敛——即使最终收敛了数字也可疑可能是热降频、吵闹的邻居进程、后台任务。文档给出的处理顺序过段时间再试或换一台更安静的机器先判断波动是否真实存在你的代码本身是否有方差若大多数 benchmark 都收敛而只有一个不收敛该 benchmark 本身可能天生噪声大数据依赖分支、内存分配等用--bm_min_secs强制更长的运行以平均掉短期噪声或者接受超时——至少你由此知道这些数字是可疑的。另外注意参数组合的硬性校验直接由 Benchmark.cpp 报 fatal--bm_min_secs不得大于--bm_max_secs--bm_target_percentile、--bm_target_precision_pct、--bm_min_secs、--bm_min_samples都要求搭配--bm_modeadaptive使用--bm_perf_argsperf 采样在 adaptive 模式下不受支持需要时用--bm_modebest-of。adaptive 不能解决的问题与跨运行比较文档明确列出了 adaptive 模式不提供保证的范围长期系统状态变化持续时间长于一次运行几十秒量级的状态变化不可见可能出现本次运行稳定收敛、下次运行对不上的情况。二进制布局差异微基准对指令缓存对齐敏感看似无害的代码改动也可能使耗时偏移几个百分点。文档实测向verboseLogFinal()加一段死代码就持续改变了测量结果二进制布局效应轻松引入 5–20% 的方差因此不要把 0.1% 的精度目标当真。所以 adaptive 的正确用途是消除同一次运行内比较的运气成分而不是获得完美的绝对值。做跨运行比较比如你的 commit 对比基线时文档建议尽量在同一会话内背靠背运行两个构建间隔几分钟到几小时重复运行以捕获长期漂移看 benchmark 之间的相对差异而不是绝对值有条件的话在专用基准硬件上运行。收敛的 adaptive 结果与 best-of 模式的好运行结果非常接近由于 best-of 取最小值p0而 adaptive 默认取 p33同样的二进制在安静系统上 adaptive 的数值会略偏高但在噪声系统上更可重复。【免费下载链接】follyAn open-source C library developed and used at Facebook.项目地址: https://gitcode.com/GitHub_Trending/fol/folly创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
