Visual c++ &引用;“逃避”;及;“重击”;MSVC中的等价物
在中,他介绍了两个神奇的功能,可以在没有任何额外性能损失的情况下击败优化器 以下是函数(使用GNU样式的内联汇编)供参考: 它适用于任何支持GNU风格内联汇编的编译器(GCC、Clang、英特尔编译器,可能还有其他编译器)。然而,他提到它在MSVC中不起作用 通过检查,他们似乎使用了对Visual c++ &引用;“逃避”;及;“重击”;MSVC中的等价物,visual-c++,benchmarking,microbenchmark,Visual C++,Benchmarking,Microbenchmark,在中,他介绍了两个神奇的功能,可以在没有任何额外性能损失的情况下击败优化器 以下是函数(使用GNU样式的内联汇编)供参考: 它适用于任何支持GNU风格内联汇编的编译器(GCC、Clang、英特尔编译器,可能还有其他编译器)。然而,他提到它在MSVC中不起作用 通过检查,他们似乎使用了对volatile const char&的重新解释转换,并将其传递给非gcc/clang编译器上隐藏在不同翻译单元中的函数 template <class Tp> inline BENCHMARK_AL
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*) {}
模板
内联基准\u始终\u内联无效未优化(Tp常量和值){
内部::UseCharPointer(&reinterpret_cast(值));
}
//其他翻译单位
void UseCharPointer(字符常量volatile*){}
然而,我对此有两个担忧:
MSVC中是否有任何与GNU风格的汇编函数相对应的低级功能?或者这是MSVC上最好的功能了?虽然我不知道MSVC有类似的组装技巧,但Facebook在其愚蠢基准库中使用了以下功能:
/**
* 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
/**
*针对您所使用的变量调用doNotOptimizeAway(var)
*基准测试在其他方面都是无用的。编译器倾向于执行
*在消除未使用的变量方面做得很好,这个函数很愚蠢
*事实上,我们需要它来思考var。
*/
#ifdef硕士学位
#pragma优化(“,关闭)
模板
void dono优化中途(T&基准){
基准=基准;
}
#pragma优化(“,打开)
#已定义的elif(_-clang__;)
模板
__属性uu((uuu optnone_uuuuu))void不优化(T&&/*datum*/){}
#否则
模板
void dono优化中途(T&基准){
asm volatile(“:”+r(基准));
}
#恩迪夫
我正在寻找一种方法,在我自己的小基准库中实现完全相同的功能。 MSVC令人沮丧的是,针对x64不允许使用asm技巧,而x86允许使用 经过几次尝试后,我重新使用了谷歌的解决方案,没有引起额外的呼叫! 很好的一点是,该解决方案可以与MSVC(/Ox)和GCC(-O3)一起使用 生成的ASM()
MSVC风格的asm{}无论如何也不会特别有用;它没有任何类似GNU C inline asm的输入/输出约束,让您告诉编译器,asm的空块实际上读取或读取写入了一个C变量,以迫使编译器在寄存器中具体化该变量。易失性负载迫使编译器在内存中具体化它,而不仅仅是
mov edx,10
什么的。但至少编译器仍然知道var只是在被读取,所以返回一个代码>仍然可以编译到存储/重新加载之间的mov eax,10
。但是,这看起来仍然会在使用它的地方引入2条指令,除非var已经存在于内存中,否则您只会得到一个加载。因此,在不太干扰编译器生成的代码的情况下,这可能很有用,但绝对不是免费的。对于窄类型(sizeof(T)Related):询问原始GNU C内联asm版本的真正功能。
/**
* 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
template <class T>
inline auto doNotOptimizeAway(T const& datum) {
return reinterpret_cast<char const volatile&>(datum);
}
int main()
{
int a{10};
doNotOptimizeAway(a);
return 0;
}
a$ = 8
main PROC
mov DWORD PTR a$[rsp], 10
movzx eax, BYTE PTR a$[rsp]
xor eax, eax
ret 0
main ENDP