如何不优化 - 愚蠢函数的机制

How not to optimize away - mechanics of a folly function

本文关键字:函数 机制 何不 优化      更新时间:2023-10-16

我正在寻找一种编程技术,以确保用于基准测试的变量(没有可观察到的副作用)不会被编译器优化

这提供了一些信息,但我最终使用了愚蠢和以下函数

/**
 * Call doNotOptimizeAway(var) against variables that you use for
 * benchmarking but otherwise are useless. The compiler tends to do a
 * good job at eliminating unused variables, and this function fools
 * it into thinking var is in fact needed.
 */
#ifdef _MSC_VER
#pragma optimize("", off)
template <class T>
void doNotOptimizeAway(T&& datum) {
  datum = datum;
}
#pragma optimize("", on)
#else
template <class T>
void doNotOptimizeAway(T&& datum) {
  asm volatile("" : "+r" (datum));
}
#endif

我想使用上述内容,但我对其工作原理知之甚少。我最感兴趣的是非VC++部分以及为什么/如何行

asm volatile("" : "+r" (datum));

创建一个不可优化的上下文,或者为什么人们会选择实现这样的事情。两种方法之间的比较也会很有趣(我不知道pragma optimize是如何工作的,但它看起来像一个更干净的解决方案 - 虽然不便携)

没有

标准方法可以停用优化,因此,如果您需要停用优化,则只能使用您的实现提供的任何功能。比较这两种方法没有意义,除非您找到支持这两种方法的编译器。

无论如何,在海湾合作委员会,

asm volatile("" : "+r" (datum));

表示用户提供的未经验证的汇编代码嵌入到 GCC 生成的汇编中。第一个字符串文字 ("") 包含要注入的汇编代码。它是空的,所以实际上根本没有发出任何代码。

:后面的部分通知 GCC 汇编代码的影响。 "+r" (datum)意味着GCC应该假设汇编代码读取并修改datum。即使它没有。这样做的原因是,任何最终将值存储在datum中的早期计算都不能因为不必要的而丢弃。同时,汇编代码本身不能因为不必要而被丢弃,因为可能会对datum进行修改。 volatile还将汇编代码标记为不得优化的代码,如下所述:

GCC 的优化器有时会在确定不需要输出变量时丢弃asm语句。此外,如果优化器认为代码将始终返回相同的结果(即其输入值在调用之间没有变化),则可能会将代码移出循环。使用 volatile 限定符将禁用这些优化。[...]

使用两种不同的方法来防止删除汇编代码似乎有点多,真的,但我想最好确定一下。

r约束意味着代码并不关心GCC为汇编代码提供的寄存器,并记录在这里:

'

r'
    允许使用寄存器操作数,前提是它位于常规寄存器中。

+修饰符意味着代码可以读取和写入datum,并记录在这里:

"+"
    表示此操作数由指令读取和写入。[...]