likely与unlikely函数的意义.doc_第1页
likely与unlikely函数的意义.doc_第2页
likely与unlikely函数的意义.doc_第3页
likely与unlikely函数的意义.doc_第4页
likely与unlikely函数的意义.doc_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

关于likely()与unlikely函数 分类: 嵌入式 Linux内核 2011-11-29 19:55 378人阅读 评论(0) 收藏 举报 优化编译器gcc支声明对于条件选择语句,gcc内建了一条指令用于优化,在一个条件经常出现,或者该条件很少出现的时候,编译器可以根据这条指令对条件分支选择进行优化。内核把这条指令封装成了宏,比如likely()和unlikely(),这样使用起来比较方便。例如,下面是一个条件选择语句:if (foo) /* . */如果想要把这个选择标记成绝少发生的分支:/* 我们认为foo绝大多数时间都会为0. */if (unlikely(foo) /* . */相反,如果我们想把一个分支标记为通常为真的选择:/* 我们认为foo通常都不会为0 */if(likely(foo) /* . */ likely()与unlikely()函数的意义 2013-03-03 15:32:42 分类: 嵌入式看内核时总遇到if(likely( )或是if(unlikely( )这样的语句,最初不解其意,现在有所了解,所以也想介绍一下。likely() 与 unlikely()是内核(我看的是版本,2.6的版本应该都有)中定义的两个宏。位于/include/linux/compiler.h中,具体定义如下:#define likely(x) _builtin_expect(!(x), 1)#define unlikely(x) _builtin_expect(!(x), 0)_builtin_expect是gcc(版本=2.96,网上写的,我没验证过)中提供的一个预处理命令(这个名词也是网上写的,我想叫函数更好些),有利于代码优化。gcc(version 4.4.0)具体定义如下:long _builtin_expect (long exp, long c) Built-in Function注解为:You may use _builtin_expect to provide the compiler with branch prediction information. In general, you should prefer to use actual profile feedback for this (-fprofile-arcs), as programmers are notoriously bad at predicting how their programs actually perform. However, there are applications in which this data is hard to collect.The return value is the value of exp, which should be an integral expression. The semantics of the built-in are that it is expected that exp = c.它的意思是:我们可以使用这个函数人为告诉编绎器一些分支预测信息“exp=c” 是“很可能发生的”。#define likely(x) _builtin_expect(!(x), 1)也就是说明x=1是“经常发生的”或是“很可能发生的”。使用likely ,执行if后面语句的可能性大些,编译器将if是的内容编译到前面, 使用unlikely ,执行else后面语句的可能性大些,编译器将else里的内容编译到前面。这样有利于cpu预取,提高预取指令的正确率,因而可提高效率。举个例子(内核版本):/kernel/shed.c中有一段:if (likely(!active_balance) /* We were unbalanced, so reset the balancing interval */sd-balance_interval = sd-min_interval; else /* If weve begun active balancing, start to back off. This* case may not be covered by the all_pinned logic if there* is only 1 task on the busy runqueue (because we dont call* move_tasks).*/if (sd-balance_interval max_interval)sd-balance_interval *= 2;编译过程中,会将if后面里的内容编译到前面,else 后面里的内容编译到后面。若将likely换成unlikely 则正好相反。总之,likely与unlikely互换或不用都不会影响程序的正确性。但可能会影响程序的效率。 if(likely(foo) /认为foo通常为1 if(unlikely(foo) /认为foo通常为0 详解likely和unlikely函数 分类: ARM 相关 linux内核分析 2012-06-13 23:28 784人阅读 评论(0) 收藏 举报 branchlinux内核优化gccstruct文档内核源码:linux-.tar.bz2 参考文档:/onlinedocs/gcc-4.6.2/gcc/Other-Builtins.html#Other-Builtins 在Linux内核中likely和unlikely函数有两种(只能两者选一)实现方式,它们的实现原理稍有不同,但作用是相同的,下面将结合linux-版本的内核代码来进行讲解。 1、对_builtin_expect的封装 它们的源代码如下:cpp view plaincopyprint?1. /*linux-/include/linux/compiler.h*/2. #definelikely(x)_builtin_expect(!(x),1)3. #defineunlikely(x)_builtin_expect(!(x),0) _builtin_expect是GCC的内置函数,用来对选择语句的判断条件进行优化,常用于一个判断条件经常成立(如likely)或经常不成立(如unlikely)的情况。 _builtin_expect的函数原型为long _builtin_expect(long exp, long c),返回值为完整表达式exp的值,它的作用是期望表达式exp的值等于c(注意,如果exp = c条件成立的机会占绝大多数,那么性能将会得到提升,否则性能反而会下降)。 在普通的应用程序中也可以使用_builtin_expect,如下面的例子:cpp view plaincopyprint?1. #include2. 3. intmain(void)4. 5. inta;6. 7. scanf(%d,&a);8. 9. if(_builtin_expect(a,4)10. printf(if:a=%dn,a);11. else12. printf(else:a=%dn,a);13. 14. return0;15. 分别输入整数0到4来进行5次测试,它们的输出分别为:cpp view plaincopyprint?1. else:a=02. 3. if:a=14. 5. if:a=26. 7. if:a=38. 9. if:a=4 注意,在上例中只有输入整数0的时候才执行else后的打印语句,也就是说_builtin_expect(a, 4)函数的值就是表达式a的值。 记住,它们只是用来提升性能的优化手段,并不会改变原来表达式的值。 2、使用_branch_check_函数 它们的源代码如下:cpp view plaincopyprint?1. /*linux-/include/linux/compiler.h*/2. #ifndeflikely3. #definelikely(x)(_builtin_constant_p(x)?!(x):_branch_check_(x,1)4. #endif5. #ifndefunlikely6. #defineunlikely(x)(_builtin_constant_p(x)?!(x):_branch_check_(x,0)7. #endif (1)、先使用内置函数_builtin_constant_p忽略表达式x为常量的情况 _builtin_constant_p也是GCC的内置函数,函数原型为int _builtin_constant_p(exp),用于判断表达式exp在编译时是否是一个常量,如果是则函数的值为整数1,否则为0,如下面的例子:cpp view plaincopyprint?1. #include2. #include3. 4. #defineVALUE55. 6. intmain(void)7. 8. char*ptr=NULL;9. intnum,count;10. 11. ptr=malloc(20);12. num=_builtin_constant_p(ptr)?20:20+10;13. printf(num=%dn,num);14. free(ptr);15. 16. count=_builtin_constant_p(VALUE)?20+VALUE:10;17. printf(count=%dn,count);18. 19. return0;20. 例子的输出结果:cpp view plaincopyprint?1. num=302. count=25 例子中的ptr为指针变量,所以_builtin_constant_p(ptr)的值为0,num的值为30。 (2)、函数_branch_check_的实现cpp view plaincopyprint?1. /*linux-/include/linux/compiler.h*/2. #define_branch_check_(x,expect)(3. int_r;4. staticstructftrace_branch_data5. _attribute_(_aligned_(4)6. _attribute_(section(_ftrace_annotate

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论