C 是否可以告诉分支预测器跟踪分支的可能性有多大?

C 是否可以告诉分支预测器跟踪分支的可能性有多大?,c,gcc,x86,compiler-optimization,micro-optimization,C,Gcc,X86,Compiler Optimization,Micro Optimization,我只是想说清楚,我不打算在这里实现任何形式的可移植性,所以任何将我绑定到某个盒子上的解决方案都是好的 基本上,我有一个if语句,它将99%的时间求值为true,并且我正试图弥补性能的每一个最后时钟,我是否可以发出某种编译器命令(使用GCC 4.1.2和x86 ISA,如果重要的话)来告诉分支预测器它应该为该分支缓存?是的 \u内置的expect是一种 gcc(版本>=2.96)提供 程序员指示分支 将预测信息发送到 编译器。的返回值 \u内置\u expect是第一个参数(只能是整数) 传给它

我只是想说清楚,我不打算在这里实现任何形式的可移植性,所以任何将我绑定到某个盒子上的解决方案都是好的

基本上,我有一个if语句,它将99%的时间求值为true,并且我正试图弥补性能的每一个最后时钟,我是否可以发出某种编译器命令(使用GCC 4.1.2和x86 ISA,如果重要的话)来告诉分支预测器它应该为该分支缓存?

是的

\u内置的expect
是一种 gcc(版本>=2.96)提供 程序员指示分支 将预测信息发送到 编译器。的返回值
\u内置\u expect
是第一个参数(只能是整数) 传给它

\u内置的expect
是一种 gcc(版本>=2.96)提供 程序员指示分支 将预测信息发送到 编译器。的返回值
\u内置\u expect
是第一个参数(只能是整数) 传给它


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

此外,必须对过早优化及其危害进行评论


编辑:Drakosha提到了GCC的一些宏。但是,我相信这是一个代码优化,实际上与分支预测无关。

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

此外,必须对过早优化及其危害进行评论


编辑:Drakosha提到了GCC的一些宏。然而,我相信这是一种代码优化,实际上与分支预测无关。

我觉得这听起来有点过头了——这种类型的优化将节省很少的时间。例如,使用更现代的gcc版本将对优化产生更大的影响。另外,尝试启用和禁用所有不同的优化标志;它们并不都能提高性能

基本上,与许多其他富有成效的途径相比,这似乎极不可能产生任何显著的差异


编辑:谢谢你的评论。我制作了这个社区wiki,但保留了它,以便其他人可以看到评论。

我觉得这听起来有点过分-这种类型的优化将节省很少的时间。例如,使用更现代的gcc版本将对优化产生更大的影响。另外,尝试启用和禁用所有不同的优化标志;它们并不都能提高性能

基本上,与许多其他富有成效的途径相比,这似乎极不可能产生任何显著的差异


编辑:谢谢你的评论。我创建了这个社区wiki,但保留了它,以便其他人可以看到评论。

SUN C Studio为这种情况定义了一些pragmas

#pragma很少被称为()

如果条件表达式的一部分是函数调用或以函数调用开头,则此操作有效


但是没有办法标记一个通用的if/while语句,suncstudio为这种情况定义了一些pragma

#pragma很少被称为()

如果条件表达式的一部分是函数调用或以函数调用开头,则此操作有效

但是没有办法标记一个通用的if/while语句,奔腾4(又称Netburst微体系结构)将分支预测器提示作为jcc指令的前缀,但只有P4使用过它们。 看见及 从…起他有一个C++优化指南,

更早和更高版本的x86 CPU会自动忽略这些前缀字节。提到PowerPC有一些跳转指令,其中包含分支预测提示作为编码的一部分。这是一个非常罕见的建筑特征。在编译时静态地预测分支是非常困难的,所以通常最好让硬件来解决它

关于最新的Intel和AMD CPU中的分支预测器和分支目标缓冲区的具体行为,官方没有发表多少文章。优化手册(在AMD和Intel的网站上很容易找到)提供了一些建议,但没有记录具体的行为。一些人已经运行了测试,试图预测实现,例如Core2有多少BTB条目。。。无论如何,明确暗示预测者的想法已经被放弃(现在)

例如,有文献记载的是,Core2有一个分支历史缓冲区,如果循环总是运行一个恒定的短迭代次数,<8或16 IIRC,则可以避免错误预测循环退出。但不要太快展开,因为适合64字节(或Penryn上的19uops)的循环不会有指令获取瓶颈,因为它从缓冲区重放。。。去看Agner Fog的PDF吧,它们很棒

另请参见:英特尔,因为Sandybridge根本不使用静态预测,从试图对CPU进行反向工程的性能实验中我们可以看出。(许多较旧的CPU在动态预测未命中时将静态预测作为回退。正常的静态预测是不采用前向分支,而采用后向分支(因为后向分支通常是循环分支)


使用GNU C的
\u内置的
\u expect
(如Drakosha的回答中提到的)宏的
可能()
/
不可能()
的效果不会直接将BP提示插入asm
。(它可能在使用
gcc-march=pentium4
时这样做,但在编译其他任何东西时则不这样做)

实际效果是对代码进行布局,以使快速路径具有更少的分支,并且可能具有更少的指令总数。这将有助于在静态预测发挥作用的情况下进行分支预测(例如,在CPU上的动态预测是冷的,而CPU上的预测确实会回退)
if (__builtin_expect (x, 0))
                foo ();

     [This] would indicate that we do not expect to call `foo', since we
     expect `x' to be zero.