Visual studio MSVC的可能/不可能等效物

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上的(空出)*可能。您不会错过的。根据英特尔的文档:

GCC编译器支持用于定义可能宏和不可能宏的内置expect语句

例如

Microsoft Visual C编译器是否有等效语句或等效语句?

应该类似

然而,如果你想做得很好,你应该使用提示而不是静态提示。

我说的是平底船 没有比这更好的了。有,但不要使用它,它是另一种优化器指令

实际上,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年开始,可能要长得多
  • 武器4.1
  • IBM XL C/C++至少从10.1开始,可能更长
  • 从6.1开始
  • TinyCC自0.9.27以来
GCC 9+还支持。它在其他任何地方都不可用,但希望有一天……要想弄清楚是否使用Ilkley/Loppen,需要进行大量的猜测。您只需设置概率,编译器(理论上)就会做正确的事情

此外,clang支持a(从3.8开始,但使用
对其进行测试\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