【问题标题】:How not to optimize away - mechanics of a folly function如何不优化 - 愚蠢函数的机制
【发布时间】:2015-02-02 21:26:05
【问题描述】:

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

This 提供了一些信息,但我最终使用了folly 和以下函数

/**
 * 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 是如何工作的,但它看起来像一个更清洁的解决方案 - 虽然不可移植)

【问题讨论】:

标签: c++ c++11 assembly benchmarking c++14


【解决方案1】:

没有禁用优化的标准方法,因此如果您需要禁用优化,您将受限于您的实现碰巧提供的任何内容。除非您找到支持这两种方法的编译器,否则比较这两种方法是没有意义的。

无论如何,在 GCC 中,

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

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

: 之后的部分通知 GCC 汇编代码的效果。 "+r" (datum) 表示 GCC 应该假定汇编代码读取和修改 datum。即使它没有。这样做的原因是,任何最终将值存储在datum 中的早期计算都不能因为不必要而被丢弃。同时,由于对datum 的潜在修改,汇编代码本身不能因为不必要而被丢弃。 volatile 还将汇编代码标记为不能优化掉的代码,as documented here

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

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

r 约束意味着代码并不关心 GCC 提供哪些寄存器供汇编代码使用,is documented here

‘r’
允许使用寄存器操作数,前提是它位于通用寄存器中。

+ 修饰符意味着代码可以读取和写入datumis documented here

‘+’
表示该操作数由指令读取和写入。 [...]

【讨论】:

    猜你喜欢
    • 2019-03-16
    • 1970-01-01
    • 1970-01-01
    • 2019-03-08
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    • 2011-08-24
    • 2012-05-09
    相关资源
    最近更新 更多