是否有可能告诉分支预测器跟随分支的可能性?

为了说清楚,我不打算在这里进行任何移植,所以任何将我绑定到某个盒子的解决scheme都是可以的。

基本上,我有一个if语句,将99%的时间评估为真,并试图排除性能的每一个时钟,我可以发出某种编译器命令(使用GCC 4.1.2和x86 ISA,如果它很重要)告诉分支预测器,它应该caching该分支?

是。 http://kerneltrap.org/node/4705

__builtin_expect是gcc(versions> = 2.96)为程序员提供分支预测信息给编译器的方法。 __builtin_expect的返回值是传递给它的第一个参数(只能是一个整数)。

 if (__builtin_expect (x, 0)) foo (); [This] would indicate that we do not expect to call `foo', since we expect `x' to be zero. 

是的,但它不会起作用。 在Netburst之前的例外是旧的(过时的)体系结构,即便如此,它也没有做任何可衡量的事情。

英特尔在Netburst体系结构中引入了一个“分支提示”操作码,在某些较旧的体系结构上有一个默认的冷跳转静态分支预测(后向预测采用,预测未采用)。 GCC使用__builtin_expect (x, prediction)实现这一点,其中预测通常是0或1.编译器发出的操作码在所有较新的处理器架构(> = Core 2)上被忽略 。 在这个实际上做些什么的小angular落案例是旧Netburst体系结构上的一次冷战。 英特尔现在build议不要使用静态分支提示,可能是因为他们认为代码大小的增加比可能的边际加速更有害。

除了预测器无用的分支提示之外, __builtin_expect也有其用处,编译器可以对代码进行重新sorting以提高caching使用率或节省内存。

有多种原因不能按预期工作。

  • 处理器可以完美地预测小环路(n <64)。
  • 处理器可以完美地预测小的重复模式(n〜7)。
  • 处理器本身可以在编译期间比编译器/程序员更好地估计分支运行期间的概率。
  • 一个分支的可预测性 (一个分支将得到正确预测的概率)远比分支被采用的概率重要得多。 不幸的是,这是高度依赖于build筑的,而预测分支的可预测性是非常困难的。

阅读更多关于Agner Fogs 手册中分支预测的内部工作。 另请参阅gcc 邮件列表 。

就像Drakosha说的那样,告诉gcc哪个分支是常见的情况,所以它为分支预测器是冷的情况生成更好的代码,所以通过函数的快速path很容易执行,这可能是非常有用的。

仅供参考,Pentium 4将分支预测提示作为jcc指令的前缀,但是只有netburst微体系结构对它们做过任何事情。 请参阅http://ref.x86asm.net/geek32.html 。 Agner Fog的3.5节是优秀的ASMselect指南 ,来自http://www.agner.org/optimize/ 。 他也有一个用C ++优化的指南。

关于最近的英特尔和AMD处理器的分支预测器和分支目标缓冲器的performance,正式发布的并不多。 优化手册(在AMD和英特尔的网站上很容易find)提供了一些build议,但不logging具体的行为。 有些人已经进行了testing来试图推测实现,例如Core2有多lessBTB条目……无论如何,明确暗示预测variables的想法已经被放弃了(现在)。 例如,Core2有一个分支历史logging缓冲区,如果循环总是运行一个不变的短迭代次数<8或16 IIRC,就可以避免错误预测循环退出。 但是不要太快地展开,因为64bytes(或者Penryn上的19uops)的循环不会有指令取出的瓶颈,因为它从缓冲区重放…阅读Agner Fog的pdf,它们非常棒

我build议不要担心分支预测,剖析代码并优化代码以减less分支数量。 一个例子是循环展开,另一个使用布尔编程技术,而不是使用if语句。

大多数处理器都喜欢预取语句。 通常,分支语句会在处理器中产生一个错误 ,导致它冲刷预取队列。 这是最大的惩罚。 为了减less这个惩罚时间,重写(和devise)代码,以便更less的分支可用。 而且,一些处理器可以有条件地执行指令而不必分支。

我已经使用循环展开和大型I / O缓冲区将程序从1小时的执行时间优化到2分钟。 分支预测在这种情况下不会节省很多时间。

SUN C Studio为这种情况定义了一些编译指示。

#pragma rare_called()

如果一个条件expression式的一部分是一个函数调用或者以一个函数调用开始,这就可以工作。

但是没有办法标记一个通用的if / while语句

不,因为没有汇编命令让分支预测器知道。 别担心,分支预测器非常聪明。

此外,关于不成熟的优化和它是如何邪恶的强制性评论。

编辑:Drakosha提到一些海湾合作委员会的macros。 不过,我相信这是一个代码优化,实际上与分支预测无关。

这听起来像是过度杀伤 – 这种优化会节省很less的时间。 例如,使用更现代版本的gcc将对优化有更大的影响。 另外,尝试启用和禁用所有不同的优化标志; 他们并不都提高了performance。

基本上,这与其他许多富有成果的path相比,这似乎是极不可能的。

编辑:感谢您的意见。 我已经制作了这个社区维基,但留下来让其他人可以看到评论。