我不明白 DoNotOptimizeAway 的定义

I don't understand the definition of DoNotOptimizeAway

我正在检查 Celero git repository DoNotOptimizeAway 的含义。但我还是不明白。你能帮我用外行的方式理解它吗?尽你所能。

The celero::DoNotOptimizeAway template is provided to ensure that the optimizing compiler does not eliminate your function or code. Since this feature is used in all of the sample benchmarks and their baseline, it's time overhead is canceled out in the comparisons.

您没有包含定义,仅包含文档。我认为您是在寻求帮助以了解其存在的原因,而不是定义。

它阻止编译器从重复循环中进行 CSEing 和提升工作,因此您可以重复相同的工作足够多次以进行测量。例如在一个 运行s 10 亿次的循环中放一些短的东西,然后你可以很容易地测量整个循环的时间(一秒左右)。有关在 asm 中手动执行此操作的示例,请参阅 。如果你想要这样的编译器生成的代码,你需要一个像 DoNotOptimizeAway.

这样的函数/宏

在禁用优化的情况下编译整个程序将毫无用处:storing/reloadingC++ 语句之间的所有内容都会产生截然不同的瓶颈(通常是存储转发延迟)。参见

另请参阅 了解一般的微基准测试陷阱


也许查看实际定义也会有所帮助。

此问答 (Optimization barrier for microbenchmarks in MSVC: tell the optimizer you clobber memory?) 描述了 DoNotOptimize 宏的一种实现方式(并询问如何将其从 GNU C++ 移植到 MSVC)。

escape 宏来自 Chandler Carruth 的 CppCon2015 演讲,"Tuning C++: Benchmarks, and CPUs, and Compilers! Oh My!"。该演讲还详细说明了编写微基准测试时为什么需要它:在启用优化的情况下编译时阻止整个循环优化。

(如果有问题,让编译器将事物从循环中提升出来而不是重复计算它们会更难解决问题。创建一个函数 __attribute__((noinline)) 如果它足够大而不是 需要内联。检查编译器的 asm 输出以查看它提升了多少设置。)


顺便说一句,GNU C/C++ 的良好定义通常具有零额外成本:
asm volatile("" :: "r"(my_var)); 编译为零 asm 指令,但要求编译器在其选择的寄存器中具有 my_var 的值。 (并且由于 asm volatile,在 C++ 抽象机中必须多次“运行”)。

这只会影响优化,前提是编译器可以将其所属的计算转换为其他内容。 (例如,在循环计数器上使用它会阻止编译器仅使用指针增量并与结束指针进行比较以执行 for(i=0;i<n;i++) sum+=a[i];

的正确迭代次数

使用像 asm volatile("" :"+r"(my_var)); 这样的读-修改-写操作数会强制编译器忘记它所知道的关于该值的所有范围限制或常量传播信息,并将其视为传入函数 arg。例如它是 42,或者它是非负数。这可能会更多地影响优化。


当他们说“开销在比较中被抵消”时,他们希望不是在谈论从单个计时结果中显式减去任何东西,也不是在谈论基准测试 DoNotOptimizeAway 本身。

那是行不通的。现代 CPU 的性能分析 而不是 通过将每条指令的成本相加来进行。乱序流水线执行意味着如果前端(总指令吞吐量)不是瓶颈,并且它需要的执行单元也不是瓶颈,那么额外的 asm 指令可以很容易地实现零额外成本。

如果他们的可移植定义类似于 volatile T sink = input;,那么额外的 asm 存储只有在您的代码在缓存的存储吞吐量上出现瓶颈时才会产生成本。

所以关于抵消的说法听起来有点乐观。正如我上面所解释的,加上上面的上下文/优化相关因素。有可能 DoNotOptimizeAway)


同功能相关问答:

  • Preventing compiler optimizations while benchmarking
  • "Escape" and "Clobber" equivalent in MSVC