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



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

作为参考,以下是函数(使用GNU风格的内联汇编):

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

它适用于任何支持GNU风格内联汇编的编译器(GCC、Clang、英特尔编译器,可能还有其他编译器)。然而,他提到这在微软风投公司是行不通的。

检查Google Benchmark的实现,他们似乎使用了对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*) {}

然而,我对此有两个担忧:

  1. 我可能会引发函数调用
  2. 一个"聪明"的链接时间优化器可能会识别出UseCharPointer很小,将其内联,然后丢弃我想要保留的所有代码,或者一个"巧妙"的优化器可能会被允许执行我不希望它执行的其他重新排序

在MSVC中是否有GNU风格的汇编函数的较低级别等价物?或者这是微软风投上最好的一次?

虽然我不知道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

这是GitHub上的代码链接。

我一直在寻找一种方法,在我自己的小基准库中实现完全相同的东西。MSVC令人沮丧的是,针对x64不允许__asm技巧,而x86允许!

经过一些尝试,我重新使用了谷歌的解决方案,而没有招致额外的呼叫!好的是,该解决方案可以同时使用MSVC(/Ox)和GCC(-O3)。

template <class T>
inline auto doNotOptimizeAway(T const& datum) {
    return reinterpret_cast<char const volatile&>(datum);
}

在调用站点我根本不使用volatile返回!

int main()
{
    int a{10};
    doNotOptimizeAway(a);
    return 0;
}

生成的ASM(编译器资源管理器)

a$ = 8
main    PROC
        mov     DWORD PTR a$[rsp], 10
        movzx   eax, BYTE PTR a$[rsp]
        xor     eax, eax
        ret     0
main    ENDP

相关内容

  • 没有找到相关文章

最新更新