Visual studio MSVC的可能/不可能等效物
GCC编译器支持用于定义可能宏和不可能宏的内置expect语句 例如 Microsoft Visual C编译器是否有等效语句或等效语句?应该类似 然而,如果你想做得很好,你应该使用提示而不是静态提示。我说的是平底船 没有比这更好的了。有,但不要使用它,它是另一种优化器指令 实际上,gnu内置代码被包装在宏中的原因是,如果未定义Visual studio MSVC的可能/不可能等效物,visual-studio,gcc,optimization,compiler-construction,likely-unlikely,Visual Studio,Gcc,Optimization,Compiler Construction,Likely Unlikely,GCC编译器支持用于定义可能宏和不可能宏的内置expect语句 例如 Microsoft Visual C编译器是否有等效语句或等效语句?应该类似 然而,如果你想做得很好,你应该使用提示而不是静态提示。我说的是平底船 没有比这更好的了。有,但不要使用它,它是另一种优化器指令 实际上,gnu内置代码被包装在宏中的原因是,如果未定义\uu\GNUC\uu,您可以自动将其删除。这些宏一点也不需要,我打赌您不会注意到运行时的差异 总结 只要去掉非GNU上的(空出)*可能。您不会错过的。根据英特尔的文档:
\uu\GNUC\uu
,您可以自动将其删除。这些宏一点也不需要,我打赌您不会注意到运行时的差异
总结
只要去掉非GNU上的(空出)*可能
。您不会错过的。根据英特尔的文档:
为了有效地编写代码来利用这些
规则,在编写if-else或switch语句时,请检查
首先是常见案例,然后逐步降低到最不常见的情况
不幸的是,你不能写这样的东西
#define if_unlikely(cond) if (!(cond)); else
因为VS10的MSVC优化器忽略了这样的“提示”
由于我更喜欢先处理代码中的错误,所以我似乎编写的代码效率较低。
幸运的是,第二次CPU遇到分支时,它将使用其统计信息而不是静态提示。根据(第57页),即使CPU正确地动态预测,使用静态分支预测仍然是有意义的。
原因是,如果静态预测正确,L1i缓存的使用效率将更高。C++20标准将包括
[[可能]]
和[[不可能]]
分支预测属性
属性建议的最新版本可从
原始属性建议可从中找到
程序员应该更喜欢PGO。如果应用不正确,属性很容易降低性能,或者以后在程序更改时变得不正确。我知道这个问题是关于Visual Studio的,但我将尝试回答尽可能多的编译器(包括Visual Studio) 十年后有了进步!对于VisualStudio 2019,MSVC仍然不支持这样的(即使是),但是正如上面提到的Pauli Nieminen,C++ 20可以用来创建可能的/不太可能的宏,MSVC通常很快地添加对新C++标准的支持(与C不同),所以我希望Visual Studio 2021支持它们。 目前(2019-10-14)只有GCC支持这些属性,甚至仅应用于标签,但至少可以进行一些基本测试。下面是一个快速实现,您可以:
#定义可能(expr)\
( \
([](布尔值){\
开关(值){\
[[可能]]情况正确:\
返回true\
[[不太可能]]案例错误:\
返回false\
} \
}) \
(expr))
#定义不可能(expr)\
( \
([](布尔值){\
开关(值){\
[[不太可能]]情况正确:\
返回true\
[[可能]]案例错误:\
返回false\
} \
}) \
(expr))
您可能希望围绕它使用ifdef来支持无法处理它的编译器,但幸运的是,大多数编译器都支持\uuuuu内置\uu expect
:
- GCC 3.0
- 叮当声
- 国际刑事法院(ICC)至少从13年开始,可能要长得多
- IBM XL C/C++至少从10.1开始,可能更长
- 从6.1开始
- TinyCC自0.9.27以来
对其进行测试\uuuuuuu内置(\uuuuuu内置\uu不可预测)
)。因为现在很多编译器都是基于clang的,所以它可能也适用于它们
如果你想把这一切都结束并准备好,你可能会对我的一个项目感兴趣。它是一个公共域C/C++头,可以在几乎所有的编译器上运行,并包含许多有用的宏,包括、、和。它还没有C++20版本,但是
即使您不想在项目中使用Hedley,您也可能希望检查那里的实现,而不是依赖上面的列表;我可能会忘记用新信息更新这个答案,但Hedley应该总是最新的。现在他们已经实现了MS
但事实上,使用“可能”和不使用之间没有任何区别
我已经编译了这些代码,并且是相同的
我认为这可能很危险。根据微软的说法:“因为编译器生成的代码基于_假设,如果_假设语句中的表达式在运行时为false,那么代码可能无法正确运行。”@Digital-Very-true,链接到MSDN的文章描述了这些陷阱。同样,应该避免这样的静态提示,如果可能的话,您应该尝试使用PGO。对不起,PGO是PITA,特别是在任何相当复杂的库中。在我自己的代码中,我更清楚什么是可能的,什么是不可能的。我正在使用VS2010,看到编译器在使用普通if时生成了一个“jne”。但是当使用else时,编译器会生成一个“je”,并将else块放在主流之后。因此,使用MSVC,您的定义似乎确实有效。现在,如果我能从微软那里找到一个声明,说明这是一种预期的、受支持的行为…@Ruben:至少从2005年起,我就开始利用这个代码生成技巧了。在所有版本中都是这样的我有一个硬件设备,
#define if_unlikely(cond) if (!(cond)); else
int main()
{
int i = rand() % 2;
if (i) [[likely]]
{
printf("Hello World!\n");
}
else
{
printf("Hello World2%d!\n",i);
}
}
int main()
{
int i = rand() % 2;
if (i)
{
printf("Hello World!\n");
}
else [[likely]]
{
printf("Hello World2%d!\n",i);
}
}
int pdb._main (int argc, char **argv, char **envp);
0x00401040 push ebp
0x00401041 mov ebp, esp
0x00401043 push ecx
0x00401044 call dword [rand] ; pdb.__imp__rand
; 0x4020c4
0x0040104a and eax, 0x80000001
0x0040104f jns 0x401058
0x00401051 dec eax
0x00401052 or eax, 0xfffffffe ; 4294967294
0x00401055 add eax, 1
0x00401058 je 0x40106d
0x0040105a push str.Hello_World ; pdb.___C__0O_NFOCKKMG_Hello_5World__CB_6
; 0x402108 ; const char *format
0x0040105f call pdb._printf ; int printf(const char *format)
0x00401064 add esp, 4
0x00401067 xor eax, eax
0x00401069 mov esp, ebp
0x0040106b pop ebp
0x0040106c ret
0x0040106d push 0
0x0040106f push str.Hello_World2_d ; pdb.___C__0BB_DODJFBPJ_Hello_5World2__CFd__CB_6
; 0x402118 ; const char *format
0x00401074 call pdb._printf ; int printf(const char *format)
0x00401079 add esp, 8
0x0040107c xor eax, eax
0x0040107e mov esp, ebp
0x00401080 pop ebp
0x00401081 ret