使用Google Benchmark做排序算法基准测试的正确方法咨询
现有方案的正确性评估
你修改后的手动计时方案是可用的,确实解决了原始代码的核心问题:首次排序后向量变为有序,后续所有迭代测试的都是有序数组的排序性能,和预期的随机数组排序测试目标不符,且手动计时也正确排除了重排数组的开销。但这个方案不是最优实现,存在可优化的空间。
现有方案的缺陷
- 手动实现的计时精度低于Google Benchmark内置计时:内置计时会自动扣除框架自身的循环开销,且做了多平台的高精度适配,对于小尺寸数组(比如仅10个元素的排序场景),手动调用系统时钟的开销占比会显著偏高,导致测试结果误差变大
- 代码冗余,不需要自行实现计时逻辑,Google Benchmark已经提供了原生的启停计时接口
更优的实现方案
推荐使用框架内置的PauseTiming()和ResumeTiming()接口控制计时范围,同时加上防止编译器优化的标记,实现更简洁、精度更高的测试:
static void StdSort(benchmark::State& state) { const size_t arr_size = state.range(0); std::default_random_engine gen; for (auto _ : state) { // 暂停计时,准备测试数据 state.PauseTiming(); auto v = generate_random_vector(arr_size); state.ResumeTiming(); std::sort(std::begin(v), std::end(v)); // 防止编译器优化掉未被后续使用的排序操作,必须加 benchmark::DoNotOptimize(v.data()); benchmark::ClobberMemory(); } } BENCHMARK(StdSort)->Arg(10)->Arg(1000)->Arg(1'000'000);
额外的测试优化建议
- 如果需要测试排序算法在不同数据分布下的性能,可以分别构造随机数组、完全有序数组、逆序数组、高重复元素数组的生成逻辑,拆分多组测试用例
- 针对10个元素这类极小规模的排序测试,可以通过
->Iterations(xxx)手动指定更高的迭代次数,降低单次计时的误差 - 若测试超大规模数组,重排/生成数组的开销过高,可以预生成多份互不相同的随机数组,每次迭代直接取一份测试,降低数据准备环节的总耗时
内容的提问来源于stack exchange,提问作者Touloudou
相关产品推荐
相关产品推荐

