禁用优化后,quick-bench.com 基准测试要快得多
Benchmark on quick-bench.com is much faster with disabled optimizations
我创建了一个非常简单的基准测试来说明短字符串优化,并在quick-bench.com上运行它。该基准测试非常适合比较禁用/启用 SSO 的字符串类,结果与 GCC 和 Clang 非常一致。但是,我意识到当我禁用优化时,报告的时间比使用 GCC 和 Clang 启用优化(-O2
或-O3
(观察到的时间快约 4 倍。
基准在这里:http://quick-bench.com/DX2G2AdxUb7sGPE-zLRa41-MCk0。
知道是什么可能导致未优化的基准测试运行速度提高 4 倍吗?
不幸的是,我看不到生成的程序集;不知道问题出在哪里("记录反汇编"框已选中,但在我的运行中没有效果(。此外,当我使用 Google 基准测试在本地运行基准测试时,结果符合预期,即优化的基准测试运行得更快。
我还尝试在编译器资源管理器中比较这两种变体,未优化的变体似乎执行了更多指令:https://godbolt.org/z/I4a171。
因此,正如评论中所讨论的,问题在于 quick-bench.com 没有显示基准测试代码的绝对时间,而是相对于无操作基准测试所花费的时间的时间。no-op 基准测试可以在 quick-bench.com 的源文件中找到:
static void Noop(benchmark::State& state) {
for (auto _ : state) benchmark::DoNotOptimize(0);
}
运行的所有基准都编译在一起。因此,优化标志也适用于它。
重现和比较不同优化级别的无操作基准,可以看到,从-O0
到-O1
版本有大约 6 到 7 倍的加速。在比较使用不同优化标志完成的基准运行时,必须考虑基线中的此因素以比较结果。因此,在问题基准中观察到的 4 倍加速是远远不够补偿的,而且行为确实符合人们的预期。
-O0
和-O1
之间 no-op 编译的一个主要区别是,对于-O0
,Google 基准代码中有一些断言和其他附加分支,这些分支针对更高的优化级别进行了优化。
此外,在-O0
循环的每次迭代都会多次加载到寄存器中,修改并存储state
部分的内存部分,例如用于减少循环计数器和循环计数器上的条件,而-O1
版本将state
保存在寄存器中,使得不需要循环中的内存加载/存储。前者要慢得多,每次迭代至少需要几个周期来进行必要的存储转发和/或从内存重新加载。
- 使用rdtsc进行基准测试的缺点是什么
- 对 'std::thread::_M_start_thread CMake 的未定义引用进行基准测试
- 更高效地在微控制器上对C++进行基准测试
- _mm256_load_ps调试模式下导致谷歌/基准测试的分段错误
- 二叉树基准测试结果
- 如何使用谷歌基准测试对自定义界面进行基准测试
- 谷歌基准测试,如何只调用一次代码?
- 使用 std::chrono::steady_clock 对线程/异步中的代码进行基准测试
- 谷歌基准测试结果中显示的时间没有意义
- 使用 Google 基准测试时返回值会发生什么情况?
- 如何在Qt测试框架中对信号进行基准测试?
- C/C++memcpu基准测试:测量CPU和墙时间
- 如何将参数传递给Google基准测试程序
- 如何对CUDA项目进行基准测试
- 为什么这个简单的 C++ SIMD 基准测试在使用 SIMD 指令时运行速度较慢?
- 多部分基准测试的权重是多少?
- 简单的 for() 循环基准测试在任何循环绑定下花费相同的时间
- 禁用优化后,quick-bench.com 基准测试要快得多
- Winsock本地客户服务器基准测试
- webAssembly有标准的基准测试吗?