MSVC中的"Escape"和"Clobber"等效

hel*_*922 17 benchmarking microbenchmark visual-c++

Chandler Carruth的CppCon 2015演讲中,他介绍了两种神奇的功能,可以在没有任何额外性能损失的情况下击败优化器.

作为参考,这里是函数(使用GNU样式的内联汇编):

void escape(void* p)
{
    asm volatile("" : : "g"(p) : "memory");
}

void clobber()
{
    asm volatile("" : : : "memory");
}
Run Code Online (Sandbox Code Playgroud)

它适用于任何支持GNU样式内联汇编的编译器(GCC,Clang,Intel编译器,可能还有其他编译器).但是,他提到它在MSVC中不起作用.

检查Google Benchmark的实现,似乎他们使用重新解释转换为a volatile const char&并将其传递给隐藏在非gcc/clang编译器上的不同翻译单元中的函数.

template <class Tp>
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
    internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
}

// some other translation unit
void UseCharPointer(char const volatile*) {}
Run Code Online (Sandbox Code Playgroud)

但是,我对此有两个顾虑:

  1. 我可能会招致一个函数调用
  2. 有一种"聪明"的链接时优化器可能会识别出UseCharPointer很小,内联它,然后丢弃我想要保留的所有代码,或者可以允许"聪明"的优化器执行其他重新排序我不这样做想要它.

MSVC中是否有与GNU样式的汇编函数相同的低级别?或者这是MSVC上最好的?

Tim*_*jns 7

虽然我不知道 MSVC 的等效组装技巧,但 Facebook 在他们的 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)

#elif defined(__clang__)

template <class T>
__attribute__((__optnone__)) void doNotOptimizeAway(T&& /* datum */) {}

#else

template <class T>
void doNotOptimizeAway(T&& datum) {
  asm volatile("" : "+r" (datum));
}

#endif
Run Code Online (Sandbox Code Playgroud)

这是 GitHub 上代码的链接。