1. 主页
  2. 文档
  3. C语言教程
  4. C语言预处理器
  5. GCC 中的分支预测宏

GCC 中的分支预测宏

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

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

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

在以下示例中,我们将分支标记为可能为真:

const char *home_dir ;

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

对于上面的例子,我们将“if”条件标记为“likely()”为真,因此编译器将在分支之后立即放置真代码,而在分支指令中放置假代码。这样编译器就可以实现优化。但不要盲目使用“likely()”和“unlikely()”宏。如果预测正确,则表示跳转指令的周期为零,但如果预测错误,则需要几个周期,因为处理器需要刷新它的管道,这比没有预测更糟糕。

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

 

这篇文章对您有用吗?