如何不优化远离 - 愚蠢功能的机制

Lor*_*ins 19 c++ benchmarking assembly c++11 c++14

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

提供了一些信息,但我最终使用了愚蠢和以下功能

/**
 * 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
Run Code Online (Sandbox Code Playgroud)

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

asm volatile("" : "+r" (datum));
Run Code Online (Sandbox Code Playgroud)

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

小智 19

没有标准的方法来禁用优化,因此如果您需要禁用优化,则仅限于您提供的实现.除非您找到支持它们的编译器,否则比较这两种方法没有意义.

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

asm volatile("" : "+r" (datum));
Run Code Online (Sandbox Code Playgroud)

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

在之后的部分:INFORMS GCC围绕组件代码的效果."+r" (datum)意味着GCC应该假定汇编代码读取和修改datum.即使它没有.原因是任何最终存储值的早期计算datum都不能作为不必要的丢弃.同时,由于可能的修改,汇编代码本身不能作为不必要的丢弃datum.volatile还将汇编代码标记为不得优化的代码,如下所述:

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

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

r约束意味着代码并不关心所有的东西,其注册GCC提供的用于汇编代码使用,并记录在这里:

'r'
    允许寄存器操作数,前提是它在通用寄存器中.

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

'+'
    表示该操作数由指令读写.[...]