linux中 likely与unlikely

本文介绍了Linux内核中likely与unlikely宏的作用及其使用场景。通过这些宏,程序员可以告诉编译器某些条件判断的结果更倾向于真还是假,从而帮助CPU进行更好的指令预取,提升程序运行效率。

linux中 likely与unlikely ,见了不少次,但终究没体验过所谓的提高效率,所以,如果不是阅读他人的讲解,自己在码砖的时候就不能想到使用它,软实力的一个体现吧。

分享自: http://blog.youkuaiyun.com/tommy_wxie/article/details/7384641


看内核时总遇到if(likely( )){}或是if(unlikely( ))这样的语句,具体定义如下:
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)

#define likely(x) __builtin_expect(!!(x), 1)也就是说明x==1是“经常发生的”或是“很可能发生的”。
使用likely ,执行if后面语句的可能性大些,编译器将if{}是的内容编译到前面, 使用unlikely ,执行else后面语句的可能性大些,编译器将else{}里的内容编译到前面。这样有利于cpu预取,提高预取指令的正确率,因而可提高效率。

总之,likely与unlikely互换或不用都不会影响程序的正确性。但可能会影响程序的效率。

if(likely(foo))  //认为foo通常为1

if(unlikely(foo)) //认为foo通常为0


!!(x)这个操作会把 x 转化成bool值,即0或1.
<think>好的,我现在要解决用户关于likelyunlikely在编程中的含义及用法的问题。首先,我需要回忆自己之前学过的相关知识,并结合提供的引用内容来整理答案。 用户提到的这几个引用中,引用[1]提到了`__builtin_expect(EXP, N)`的用法,说明likelyunlikely是基于这个内置函数的宏,用来告诉编译器条件判断的结果更可能是什么。引用[2]指出这是Linux内核中的优化手段,用于条件分支的性能优化。引用[3]则具体解释了宏的用法,分别标记条件为真或假的可能性,帮助编译器优化代码布局。 首先,我需要解释likelyunlikely的基本含义,它们的作用是给编译器提供分支预测的信息,从而生成更高效的机器码。比如,使用likely告诉编译器这个条件很可能为真,那么编译器可能会将更可能执行的代码放在前面,减少跳转带来的性能损耗。 接下来,应该详细说明它们的实现方式,即通过GCC的`__builtin_expect`函数,将条件的期望值传递给编译器。例如,`likely(x)`实际上就是`__builtin_expect(!!(x), 1)`,而unlikely则是期望值为0。 然后,需要举例说明在代码中如何使用这两个宏,比如在条件判断语句中包裹条件表达式,帮助编译器优化分支预测。例如,在错误处理或者罕见情况的条件判断时使用unlikely,而在正常流程的条件判断时使用likely。 同时,应该提到使用这两个宏的注意事项,比如不要滥用,只在确实有明确倾向性的分支中使用,否则可能导致性能下降。另外,需要指出它们主要适用于GCC编译器,其他编译器可能有不同的实现方式。 最后,根据用户提供的示例中的结构,生成相关问题,比如优化原理、适用场景、其他优化方法的对比等。 检查是否有遗漏的部分,比如是否涵盖了定义、实现原理、代码示例、注意事项,以及相关问题是否合理。确保引用的内容被正确标注,比如引用[^2]对应Linux内核的应用,引用[^3]对应具体用法示例。 现在需要将这些内容组织成结构清晰的回答,符合用户要求的格式,使用中文,正确使用LaTeX格式,比如内联公式用$符号,独立公式用$$。不过当前问题可能不涉及数学公式,所以可能不需要使用数学表达式,但需要保持结构清晰,分点说明。 总结,回答的结构应该是: 1. 定义和作用 2. 实现原理(基于GCC内置函数) 3. 具体用法示例 4. 使用注意事项 5. 相关问题 确保每个部分都参考了提供的引用内容,并正确标注引用标识。同时,生成的代码示例需要用反引号包裹,正确显示语法高亮。</think>### likelyunlikely的含义及用法 #### 1. 定义作用 `likely`和`unlikely`是编程中用于优化条件分支性能的宏。它们通过向编译器提供分支条件的概率信息,帮助编译器生成更高效的机器码。例如: - `likely(condition)`:表示`condition`为真的概率很大。 - `unlikely(condition)`:表示`condition`为假的概率很大。 #### 2. 实现原理 这两个宏基于GCC的`__builtin_expect`内置函数实现,语法为: ```c #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) ``` - `__builtin_expect(EXP, N)`:提示编译器`EXP == N`的概率很高[^1]。 - `!!(x)`:将任意表达式转换为布尔值(0或1),确保逻辑一致性。 #### 3. 代码示例 **场景1**:处理常见路径(使用`likely`) ```c if (likely(data_valid)) { // 数据有效时的高频操作 } else { // 错误处理的低频路径 } ``` **场景2**:处理罕见错误(使用`unlikely`) ```c if (unlikely(file_open_failed)) { // 文件打开失败的异常处理 } else { // 正常文件操作 } ``` #### 4. 注意事项 1. **适用场景**:明确分支概率时使用(如错误处理、核心循环)。 2. **编译器依赖**:主要针对GCC/Clang,其他编译器需适配(如MSVC的`__assume`)。 3. **避免滥用**:错误预测可能降低CPU流水线效率。 4. **内核应用**:广泛用于Linux内核(如网络栈、文件系统)[^2]。 #### 5. 性能优化机制 编译器会根据提示调整: - **代码布局**:高频路径紧邻无跳转指令,减少流水线冲刷。 - **分支预测**:生成`cmov`等无分支指令(概率极高时)。 - 汇编对比示例: ```asm ; 使用likely时 test %eax, %eax jne .Lhigh_prob_path ; 预测不跳转 ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值