📜  GCC中的分支预测宏

📅  最后修改于: 2021-05-26 00:01:36             🧑  作者: Mango

Linux内核中最常用的优化技术之一是“ __builtin_expect”。当使用条件代码(if-else语句)时,我们通常知道哪个分支是正确的,哪个分支不是。如果编译器事先知道此信息,则它可以生成最优化的代码。

让我们从Linux内核代码“ http://lxr.linux.no/linux+v3.6.5/include/linux/compiler.h”中看到“ likely()”和“ unlikely()”宏的宏定义[行号146和147]。

#define likely(x)      __builtin_expect(!!(x), 1)
#define unlikely(x)    __builtin_expect(!!(x), 0)

在以下示例中,我们将branch标记为可能为true:

const char *home_dir ;
  
home_dir = getenv("HOME");
if (likely(home_dir)) 
    printf("home directory: %s\n", home_dir);
else
    perror("getenv");

对于上面的示例,我们将“ if”条件标记为“ likely()”为true,因此编译器将在分支后立即放置true代码,并在branch指令内放置false代码。通过这种方式,编译器可以实现优化。但是不要盲目使用“ likely()”和“ unlikely()”宏。如果预测正确,则意味着跳转指令的周期为零,但是如果预测错误,则将花费几个周期,因为处理器需要刷新其流水线,这比没有预测要糟糕。

与其他CPU操作相比,访问内存是最慢的CPU操作。为了避免这种限制,CPU使用“ CPU缓存”,例如L1缓存,L2缓存等。缓存的想法是将一部分内存复制到CPU本身。我们可以比任何其他内存更快地访问缓存。但是问题是,“缓存内存”的大小有限,我们无法将整个内存复制到缓存中。因此,CPU必须猜测在不久的将来将使用哪个内存,然后将该内存加载到CPU缓存中,而上面的宏提示将内存加载到CPU缓存中。

想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。