likely,unlikely宏与GCC内建函数__builtin_expect()
在 GCC 手册中对 __builtin_expect() 的描述是这样的:
由于大部分程序员在分支预测方面做得很糟糕,所以 GCC 提供了这个内建函数来帮助程序员处理分支预测,优化程序。其第一个参数 exp 为一个整型表达式,这个内建函数的返回值也是这个 exp ,而 c 为一个编译期常量。这个函数的语义是:你期望 exp 表达式的值等于常量 c ,从而 GCC 为你优化程序,将符合这个条件的分支放在合适的地方。一般情况下,你也许会更喜欢使用 gcc 的一个参数 '-fprofile-arcs' 来收集程序运行的关于执行流程和分支走向的实际反馈信息。
因为这个程序只提供了整型表达式,所以如果你要优化其他类型的表达式,可以采用指针的形式。
likely 和 unlikely 是 gcc 扩展的跟处理器相关的宏:
1
2
|
#define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) |
现在处理器都是流水线的,有些里面有多个逻辑运算单元,系统可以提前取多条指令进行并行处理,但遇到跳转时,则需要重新取指令,这相对于不用重新去指令就降低了速度。
所以就引入了 likely 和 unlikely ,目的是增加条件分支预测的准确性,cpu 会提前装载后面的指令,遇到条件转移指令时会提前预测并装载某个分 支的指令。unlikely 表示你可以确认该条件是极少发生的,相反 likely 表示该条件多数情况下会发生。编译器会产生相应的代码来优化 cpu 执行效率。
因此程序员在编写代码时可以根据判断条件发生的概率来优化处理器的取指操作。
例如:
1
2
3
4
5
|
int x, y; if (unlikely(x > 0)) y = 1; else y = -1; |
上面的代码中 gcc 编译的指令会预先读取 y = -1 这条指令,这适合 x 的值大于 0 的概率比较小的情况。 如果 x 的值在大部分情况下是大于 0 的,就应该用 likely(x > 0),这样编译出的指令是预先读取 y = 1 这条指令了。这样系统在运行时就会减少重新取值了。
======
内核中的 likely() 与 unlikely()
首先要明确:
- if(likely(value)) 等价于 if(value)
- if(unlikely(value)) 也等价于 if(value)
__builtin_expect() 是 GCC (version >= 2.96)提供给程序员使用的,目的是将“分支转移”的信息提供给编译器,这样编译器可以对代码进行优化,以减少指令跳转带来的性能下降。
__builtin_expect((x),1) 表示 x 的值为真的可能性更大;
__builtin_expect((x),0) 表示 x 的值为假的可能性更大。
也就是说,使用 likely() ,执行 if 后面的语句 的机会更大,使用 unlikely(),执行 else 后面的语句的机会更大。通过这种方式,编译器在编译过程中,会将可能性更大的代码紧跟着起面的代码,从而减少指令跳转带来的性能上的下降。
最新文章
- VS2012 单元测试之泛型类(Generics Unit Test)
- hdu 5641 King's Phone
- PYTHON解析XML的多种方式效率对比实测
- opencv6.4-imgproc图像处理模块之直方图与模板
- android 6.0 httpclient
- 为Hadoop配置Win8.1授时服务器
- 编译vo-aacenc遇到的问题
- 使用Intent在活动之间穿梭(《第一行代码》读书笔记)
- 包含为 HTTP 定义的状态代码的值(枚举)
- 常用的js对象扩展方法
- C++,Python,Go对照学习-02
- 使用getInstance()方法的原因及作用
- CSS3动画属性:动画(animation)
- el标签将时间戳转换为特定格式以及将数值保留特定小数
- Latex 公式居中
- wap页面缩放
- 【LeetCode】成对交换节点
- 分类算法之朴素贝叶斯分类(Naive Bayesian classification)
- VIM 实现tab标签页及分屏,切换命令
- SQLserver数据库连接问题
热门文章
- python基础之继承组合应用、对象序列化和反序列化,选课系统综合示例
- 【文件处理】RandomAccessFile
- border与background定位
- Pascal数据结构与算法
- 【Search in Rotated Sorted Array II 】cpp
- [网站公告]1月10日1:00-7:00阿里云RDS维护会造成30秒闪断
- Cookies 、 Session 和 token 的区别
- 孤荷凌寒自学python第五十二天初次尝试使用python读取Firebase数据库中记录
- ironic的自动化脚本
- Nova 如何统计 OpenStack 资源