某些软件(通常以性能为导向,例如Linux内核,DPDK)具有用于influencing branch prediction的C助手。
我有一个非常简单的代码片段(假设我知道a > b的百分比)来表示条件嵌套的问题,并在某些逻辑被嵌套时应用likely
/unlikely
:
bool foo()
{
foo1(1);
foo2(2);
/* if (unlikely(a > b)) */
/* if (a > b)*/
{
puts("Ohhh!!! Rare case");
return true;
}
return false;
}
int main(void)
{
/* if (unlikely(foo())) */
/* if (foo()) */
{
puts("Azaza");
}
}
字符串
那么,从理论上看,哪两行应该被取消以获得更高的性能?
很明显,有3种方法可以帮助编译器进行分支预测:
if (unlikely(a > b))
x...
if (unlikely(foo()))
个字符串if (a > b)
个...
个if (unlikely(foo()))
个if (unlikely(a > b))
个...
个if (foo())
个if (unlikely(a > b))
个
理论上哪种方法最有效?为什么?
1条答案
按热度按时间zfciruhq1#
据我所知,如果条件变量该高速缓存中是not,则
likely/unlikely
语句显示出最佳效果。让我更详细地解释一下。在代码中,处理器无论如何都必须执行
foo
。所以likely
在这里不会有任何强烈的影响,因为在推测执行期间没有代码路径可以跳过。* * 必须执行**函数。让我们假设您将foo
的结果保存在变量中,代码如下所示:字符串
在这种情况下,
likely(x)
可能只会影响预取器/解码器,因为处理器刚刚计算了x,并且该值很可能被缓存在L1中(除了它在那一点被中断)。然而,要得到精确的答案,必须非常了解微架构,因为当前的CPU可能非常先进,可以同时获取和解码两个分支。现在假设你有一个全局变量
volatile int c = 15
,我们修改你的代码:型
当我们执行代码时,第一次访问
b
时,它不会在该高速缓存中,处理器必须从内存中获取它。这会花费数百个CPU周期,而不是停止,CPU在不知道b
的值的情况下开始推测性地执行代码。在这种情况下,关键字likely表示我们应该执行第一个分支。注意,执行的指令在那时对外部世界不可见。现代x86处理器可以推测性地执行多达400个微操作,并且仅在预测结果为真时才提交结果。所以为了回答你的问题,我会把
likely/unlikely
关键字放在a > b
周围。