C++ 禁用优化后,quick-bench.com上的基准测试速度要快得多

C++ 禁用优化后,quick-bench.com上的基准测试速度要快得多,c++,optimization,microbenchmark,google-benchmark,C++,Optimization,Microbenchmark,Google Benchmark,我创建了一个非常简单的基准来演示短字符串优化,并在quick bench.com上运行它。该基准测试在比较禁用/启用SSO的字符串类时运行良好,结果与GCC和Clang非常一致。然而,我意识到,当我禁用优化时,报告的时间比启用优化(-O2或-O3)的时间快4倍左右,无论是使用GCC还是使用Clang 基准在这里: 知道是什么导致未优化的基准测试运行速度快4倍吗 不幸的是,我看不到生成的程序集;不知道问题在哪里(选中了“记录拆卸”框,但在我的运行中没有效果)。此外,当我使用Google bench

我创建了一个非常简单的基准来演示短字符串优化,并在quick bench.com上运行它。该基准测试在比较禁用/启用SSO的字符串类时运行良好,结果与GCC和Clang非常一致。然而,我意识到,当我禁用优化时,报告的时间比启用优化(
-O2
-O3
)的时间快4倍左右,无论是使用GCC还是使用Clang

基准在这里:

知道是什么导致未优化的基准测试运行速度快4倍吗

不幸的是,我看不到生成的程序集;不知道问题在哪里(选中了“记录拆卸”框,但在我的运行中没有效果)。此外,当我使用Google benchmark在本地运行基准测试时,结果与预期一致,即优化的基准测试运行得更快


我还尝试在Compiler Explorer中比较这两种变体,而未优化的变体似乎执行了更多的指令:。

因此,正如评论中所讨论的,问题是quick-bench.com并没有显示基准代码的绝对时间,而是相对于无操作基准所花费的时间。在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
时,循环的每次迭代将多次加载到寄存器中,修改并存储
状态的部分
,例如用于减少循环计数器和循环计数器上的条件,而
-O1
版本将在寄存器中保留
状态
,使循环中的内存加载/存储变得不必要。前者要慢得多,每次迭代至少需要几个周期来进行必要的存储转发和/或从内存重新加载。

您是否阅读了“更多->关于Quickbench”下的注释?显示的值不是绝对时间,而是相对于noop的时间(这可能也会受到优化标志的影响)。它还说,基准测试可能运行在不同的环境中,不具有可比性。@U标记您可能是对的。是的,我刚刚读了笔记,我不记得关于noop的那部分可能会受到优化标志的影响。那部分是我自己的结论,而不是实际写的内容。我没有看过源代码,但是如果它是以直接的方式实现的,那么我希望这些标志会影响noop时间。@u标记noop有几个版本:。只要你有兴趣。我们需要研究生成的汇编代码,以找出NOOP被翻译成了什么,但我在那里看不到它。甚至尝试了另一个浏览器,都没有成功。你可以看到。因此,你需要将你的时间调整大约6倍,这将使它不那么令人惊讶。