Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 可移植分支预测提示_C++_C_Optimization_C++20_Branch Prediction - Fatal编程技术网

C++ 可移植分支预测提示

C++ 可移植分支预测提示,c++,c,optimization,c++20,branch-prediction,C++,C,Optimization,C++20,Branch Prediction,是否有任何可移植的分支预测提示方法?考虑下面的例子: if (unlikely_condition) { /* ..A.. */ } else { /* ..B.. */ } 这与执行以下操作有什么不同: if (!unlikely_condition) { /* ..B.. */ } else { /* ..A.. */ } 还是使用编译器特定提示的唯一方法?(例如,GCC上的内置设备) 编译器会根据条件的顺序对if条件进行不同的处理

是否有任何可移植的分支预测提示方法?考虑下面的例子:

  if (unlikely_condition) {
    /* ..A.. */
  } else {
    /* ..B.. */
  }
这与执行以下操作有什么不同:

  if (!unlikely_condition) {
    /* ..B.. */
  } else {
    /* ..A.. */
  }
还是使用编译器特定提示的唯一方法?(例如,GCC上的内置设备)


编译器会根据条件的顺序对
if
条件进行不同的处理吗?

只需与您所做的保持一致即可。我喜欢使用

if (!(someExpression))

但是编译器应该平等对待这一点。

优化本质上是编译器的事情,因此您必须使用编译器功能来帮助它。语言本身并不关心(或要求)优化


因此,在没有编译器特定扩展的情况下,您所能做的最好的事情就是以这样一种方式组织代码,使编译器在没有帮助的情况下“做正确的事情”。但如果您想确定,请点击编译器扩展。(您可以尝试将它们抽象到预处理器后面,这样您的代码仍然可以移植。)

进行静态分支预测的标准方法是
if
被预测为未分支(即每个
if
子句被执行,而不是
else
),并执行循环和向后-
goto
s。因此,如果您期望静态预测是重要的,那么不要将常见情况放在
else
中。绕过一个未打开的循环并不容易;我从未尝试过,但我想把它放在
else
子句中应该可以非常方便地使用

许多编译器支持某种形式的
#pragma unroll
,但仍有必要使用某种
#if
来保护其他编译器

分支预测提示在理论上可以表示如何转换程序的流控制图以及如何在可执行内存中安排基本块的完整描述……因此有很多东西需要表达,而且大多数都不是很好移植


正如GNU在
\uuuu builtin\uexpect
文档中所建议的那样,概要文件引导优化优于提示,而且更省力。

在大多数情况下,以下代码

if (a)
{
   ...
}
else
{
    ...
}
实际上是

evaluate(A)

if (!A)
{
   jmp p1
}

... code A

   jmp p2

p1:

... code !A

p2:
请注意,如果A为true,“代码A”已经在管道中。处理器将看到前面的“jmp2”命令,并将p2代码加载到管道中

如果A为false,则“code!A”可能不在pipleline中,因此可能较慢

结论:

  • 如果(X)如果X的可能性大于!X

  • 尽可能早地评估A,以便CPU能够动态优化管道
  • :


    通过
    #ifdef
    检查特定编译器并将这些内容隐藏在自定义宏后面有什么不对?在没有支持这些优化提示的编译器的情况下,您可以定义它以扩展到普通表达式。我最近也做了类似的事情,GCC通过一个内在函数支持显式缓存预取

    允许编译器针对以下情况进行优化:执行路径 包括这一声明的可能性比任何其他选择都大或小 不包含此类语句的执行路径


    我想知道这是否可能是C++0x属性为
    if
    附加的条件?像
    如果([[不太可能]]不太可能的条件){…}
    ?当前语法不允许使用它。但是,它允许
    如果([[不太可能]]bool b=…){}
    。也许有人会滥用这一点:)GNU代码在完全非性能关键的代码中包含了大量的
    if(可能是(…)
    垃圾,在我看来这真的很糟糕。首先,它的英文读起来并不自然——它听起来像“如果这个条件很可能是真的”,而不是“如果这个条件是真的,那么它很可能是真的”。另一方面,这只是杂乱无章。除非您已经有很多性能关键条件无法编译为
    cmov
    或类似的条件,否则请忽略分支预测提示。@R。。我想我理解为什么Linux内核中充斥着
    if(不太可能(…)
    。他们更喜欢提前退出,使代码流更容易遵循。如果他们不这样做,那么静态分支预测总是会失败,这将使Linux的速度降低0.00001%。不可测量。如果是的话,简单地把这些废话放在几个可测量的条件中,而不是放在任何地方。这也是一种文档提示。我经常使用它来区分活动工作代码和异常错误处理代码。这说明在我所研究的体系结构中,这是一种非常有用的机制,因为ISA在分支指令(SPARC)中有提示位。VS也有PGO,所以这是一种双赢的机制。:)不过,提供优化提示的语言有很多先例(
    inline
    restrict
    register
    )。在现代编译器中,有些编译器比其他编译器更有意义。不管特定的实现是否真的对它们做了什么:如果有合理的机会做一些有用的事情,那么它将是一个很好的特性。我认为静态分支预测基本上不符合这个标准,所以我认为不考虑它不是一个坏主意。不过,这是根据案件的是非曲直做出的判断,并不完全是“我们从来都不关心优化问题”。@Steve:是的,我想我会自动忽略这些问题,所以我会忘记它们。你说得对。我认为
    restrict
    作为一种过早的优化可能是值得的。它不会造成任何伤害,通过防止可怕的存储/加载依赖性,它可能会带来显著的好处,在它应用的地方,它可能是一个文档化的需求(如
    memcpy
    ),无论这是否反映在源代码中。其他人(在C++03中),我同意你响亮的“meh”:-@Steve:我同意,我忽略了
    restrict
    ,因为它不是当前标准的一部分啊,但这是一个带标签的C和C++问题,即使是最简单的答案也可能在大量的警告中消失。我已经做到了。超过
    evaluate(A)
    
    do more stuff
    
    if (A)
       ...