C语言 为了获得更好的性能,应该将可能/不可能声明放在哪里?

tzdcorbm  于 2023-08-03  发布在  其他
关注(0)|答案(1)|浏览(70)

某些软件(通常以性能为导向,例如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种方法可以帮助编译器进行分支预测:

  1. if (unlikely(a > b)) x ...if (unlikely(foo()))个字符串
  2. if (a > b)...if (unlikely(foo()))
  3. if (unlikely(a > b))...if (foo())if (unlikely(a > b))
    理论上哪种方法最有效?为什么?
zfciruhq

zfciruhq1#

据我所知,如果条件变量该高速缓存中是not,则likely/unlikely语句显示出最佳效果。让我更详细地解释一下。
在代码中,处理器无论如何都必须执行foo。所以likely在这里不会有任何强烈的影响,因为在推测执行期间没有代码路径可以跳过。* * 必须执行**函数。让我们假设您将foo的结果保存在变量中,代码如下所示:

int x = foo();
if (likely(x))
{
    puts("Azaza");
}

字符串
在这种情况下,likely(x)可能只会影响预取器/解码器,因为处理器刚刚计算了x,并且该值很可能被缓存在L1中(除了它在那一点被中断)。然而,要得到精确的答案,必须非常了解微架构,因为当前的CPU可能非常先进,可以同时获取和解码两个分支。
现在假设你有一个全局变量volatile int c = 15,我们修改你的代码:

if (likely(b == 15))
{
    puts("Azaza");
} else {
    puts("Bzaza");
}


当我们执行代码时,第一次访问b时,它不会在该高速缓存中,处理器必须从内存中获取它。这会花费数百个CPU周期,而不是停止,CPU在不知道b的值的情况下开始推测性地执行代码。在这种情况下,关键字likely表示我们应该执行第一个分支。注意,执行的指令在那时对外部世界不可见。现代x86处理器可以推测性地执行多达400个微操作,并且仅在预测结果为真时才提交结果。
所以为了回答你的问题,我会把likely/unlikely关键字放在a > b周围。

相关问题