<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > linux內核中的likely和unlikely

linux內核中的likely和unlikely

作者: 時(shí)間:2016-11-22 來(lái)源:網(wǎng)絡(luò ) 收藏
Kernel version:2.6.14

CPU architecture:ARM920T

本文引用地址:http://dyxdggzs.com/article/201611/320003.htm

Author:ce123(http://blog.csdn.net/ce123)

GCCversion:arm-linux-gcc-3.4.1

看內核時(shí)經(jīng)常遇到if(likely( )){}或是if(unlikely( ))這樣的語(yǔ)句,不甚了解,例如(選自kernel/fork.c中copy_process):

[plain]view plaincopy
print?
  1. SET_LINKS(p);
  2. if(unlikely(p->ptrace&PT_PTRACED))
  3. __ptrace_link(p,current->parent);

下面詳細分析一下。

likely() 與 unlikely()是內核中定義的兩個(gè)宏。位于/include/linux/compiler.h中,具體定義如下:

[plain]view plaincopy
print?
  1. #definelikely(x)__builtin_expect(!!(x),1)
  2. #defineunlikely(x)__builtin_expect(!!(x),0)

__builtin_expect是GCC(version>=2.9)引進(jìn)的內建函數,其作用就是幫助編譯器判斷條件跳轉的預期值,避免跳轉造成時(shí)間亂費,有利于代碼優(yōu)化。查閱GCC手冊,發(fā)現其定義如下(http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html):

-- Built-in Function: long __builtin_expect (long EXP, long C)
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 value of C must be a compile-time constant. The
semantics of the built-in are that it is expected that EXP == C.
For example:


if (__builtin_expect (x, 0))
foo ();


would indicate that we do not expect to call `foo, since we
expect `x to be zero. Since you are limited to integral
expressions for EXP, you should use constructions such as


if (__builtin_expect (ptr != NULL, 1))
error ();


when testing pointer or floating-point values.

大致意思是:可以使用。由于大部分程序員在分支預測方面做得很糟糕,所以GCC提供了__builtin_expect這個(gè)內建函數,給編譯器提供分支預測信息,以幫助程序員處理分支預測,優(yōu)化程序。其第一個(gè)參數EXP為一個(gè)整型表達式,這個(gè)內建函數的返回值也是這個(gè)EXP,而C為一個(gè)編譯期常量,這個(gè)函數的語(yǔ)義是:你期望EXP表達式的值等于常量C,從而GCC為你優(yōu)化程序,將符合這個(gè)條件的分支放在合適的地方。由于該內建函數只提供了整型表達式,所以如果你要優(yōu)化其他類(lèi)型的表達式,可以采用指針的形式。

當GCC的版本較低時(shí)(_GNUC_MINOR__ < 96),__builtin_expect直接返回EXP。下面的代碼摘自/include/linux/compiler-gcc2.h。

[plain]view plaincopy
print?
  1. /*ThesedefinitionsareforGCCv2.x.*/
  2. /*SomewhereinthemiddleoftheGCC2.96developmentcycle,weimplemented
  3. amechanismbywhichtheusercanannotatelikelybranchdirectionsand
  4. expecttheblockstobereorderedappropriately.Define__builtin_expect
  5. tonothingforearliercompilers.*/
  6. #include
  7. #if__GNUC_MINOR__<96
  8. #define__builtin_expect(x,expected_value)(x)
  9. #endif

總結一下:if() 語(yǔ)句照常用, 和以前一樣, 只是 如果你覺(jué)得if()是1 的可能性非常大的時(shí)候, 就在表達式的外面加一個(gè)likely(),如果可能性非常小(比如幾率非常小),就用unlikely()包裹上。下面我們看一個(gè)例子。

[plain]view plaincopy
print?
  1. //test_builtin_expect.c
  2. #definelikely(x)__builtin_expect(!!(x),1)
  3. #defineunlikely(x)__builtin_expect(!!(x),0)
  4. inttest_likely(intx)
  5. {
  6. if(likely(x))
  7. x=5;
  8. else
  9. x=6;
  10. returnx;
  11. }
  12. inttest_unlikely(intx)
  13. {
  14. if(unlikely(x))
  15. x=5;
  16. else
  17. x=6;
  18. returnx;
  19. }

root@czu:~/桌面/socket# arm-linux-gcc -fprofile-arcs -O2 -c test.c

root@czu:~/桌面/socket# arm-linux-gcc -fprofile-arcs -O2 -o test test.c

root@czu:~/桌面/socket# arm-linux-objdump -D test > test.dis

[plain]view plaincopy
print?
  1. 000088cc:
  2. 88cc:e3500000cmpr0,#0;0x0
  3. 88d0:e92d4010stmdbsp!,{r4,lr}
  4. 88d4:e59fc044ldrip,[pc,#68];8920<.text+0x148>
  5. 88d8:e59fe044ldrlr,[pc,#68];8924<.text+0x14c>
  6. 88dc:e3a00005movr0,#5;0x5
  7. 88e0:0a000006beq8900//前面通過(guò)cmp將r0和0進(jìn)行比較,因為x=1的概率很大,優(yōu)先執行不等于0的分支
  8. 88e4:e89c0018ldmiaip,{r3,r4}
  9. 88e8:e3a02000movr2,#0;0x0
  10. 88ec:e3a01001movr1,#1;0x1
  11. 88f0:e0933001addsr3,r3,r1
  12. 88f4:e0a44002adcr4,r4,r2
  13. 88f8:e88c0018stmiaip,{r3,r4}
  14. 88fc:e8bd8010ldmiasp!,{r4,pc}
  15. 8900:e89e0006ldmialr,{r1,r2}
  16. 8904:e3a04000movr4,#0;0x0
  17. 8908:e3a03001movr3,#1;0x1
  18. 890c:e0911003addsr1,r1,r3
  19. 8910:e0a22004adcr2,r2,r4
  20. 8914:e3a00006movr0,#6;0x6
  21. 8918:e88e0006stmialr,{r1,r2}
  22. 891c:e8bd8010ldmiasp!,{r4,pc}
  23. 8920:000121e0andeqr2,r1,r0,ror#3
  24. 8924:000121e8andeqr2,r1,r8,ror#3
  25. 00008928:
  26. 8928:e3500000cmpr0,#0;0x0
  27. 892c:e92d4010stmdbsp!,{r4,lr}
  28. 8930:e59fc044ldrip,[pc,#68];897c<.text+0x1a4>
  29. 8934:e59fe044ldrlr,[pc,#68];8980<.text+0x1a8>
  30. 8938:e3a00005movr0,#5;0x5
  31. 893c:1a000007bne8960//前面通過(guò)cmp將r0和0進(jìn)行比較,因為x=0的概率很大,優(yōu)先執行等于0的分支
  32. 8940:e89c0018ldmiaip,{r3,r4}
  33. 8944:e3a02000movr2,#0;0x0
  34. 8948:e3a01001movr1,#1;0x1
  35. 894c:e0933001addsr3,r3,r1
  36. 8950:e0a44002adcr4,r4,r2
  37. 8954:e3a00006movr0,#6;0x6
  38. 8958:e88c0018stmiaip,{r3,r4}
  39. 895c:e8bd8010ldmiasp!,{r4,pc}
  40. 8960:e89e0006ldmialr,{r1,r2}
  41. 8964:e3a04000movr4,#0;0x0
  42. 8968:e3a03001movr3,#1;0x1
  43. 896c:e0911003addsr1,r1,r3
  44. 8970:e0a22004adcr2,r2,r4
  45. 8974:e88e0006stmialr,{r1,r2}
  46. 8978:e8bd8010ldmiasp!,{r4,pc}
  47. 897c:000121f8streqdr2,[r1],-r8
  48. 8980:000121f0streqdr2,[r1],-r0

如果我們將代碼修改一下,不用這兩個(gè)宏結果會(huì )怎樣呢?
[plain]view plaincopy
print?
  1. //test_builtin_expect.c
  2. inttest_likely(intx)
  3. {
  4. if(x)
  5. x=5;
  6. else
  7. x=6;
  8. returnx;
  9. }
  10. inttest_unlikely(intx)
  11. {
  12. if(x)
  13. x=5;
  14. else
  15. x=6;
  16. returnx;
  17. }
反匯編代碼如下:

[plain]view plaincopy
print?
  1. 00008460:
  2. 8460:e3500000cmpr0,#0;0x0
  3. 8464:03a00006moveqr0,#6;0x6
  4. 8468:13a00005movner0,#5;0x5
  5. 846c:e1a0f00emovpc,lr
  6. 00008470:
  7. 8470:e3500000cmpr0,#0;0x0
  8. 8474:03a00006moveqr0,#6;0x6
  9. 8478:13a00005movner0,#5;0x5
  10. 847c:e1a0f00emovpc,lr

如上述例子分析所示,兩個(gè)函數編譯生成的匯編語(yǔ)句所使用到的跳轉指令不一樣,仔細分析下會(huì )發(fā)現__builtin_expect實(shí)際上是為了滿(mǎn)足在大多數情況不執行跳轉指令,__builtin_expect僅僅是告訴編譯器優(yōu)化,并沒(méi)有改變其對真值的判斷。宏likely和宏unlikely唯一的作用就是選擇”將if分支還是else分支放在跳轉指令之后,從而優(yōu)化程序的執行效率”。 因為likely(EXP)代表條件表達式EXP很可能成立,而unlikely(EXP)代表條件表達式EXP很可能不成立,當程序員清楚EXP表達式 多數情況成立(不成立)時(shí),就可使用likely(unlikely),使if分支(else分支)緊跟跳轉指令其后,從而在大多數情況下不用執行跳轉指令,避開(kāi)跳轉指令所帶來(lái)的開(kāi)銷(xiāo),從而達到優(yōu)化的目的。

還有一點(diǎn)需要注意的是,在生成匯編時(shí)用的是arm-linux-gcc -fprofile-arcs -O2 -c test_builtin_expect.c,而不是arm-linux-gcc-O2 -c test_builtin_expect.c。



關(guān)鍵詞: linux內核likelyunlikel

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>