2008年3月28日 星期五

likely & unlikely

最近一直在看 code, 突然看到個很有趣的工讀生寫的 code, 裡面一堆 likely 跟 unlikely 的, 以前都沒注意到這兩個 code 的 definition, 現在終於有機會把它給翻出來檢查檢查...

在 kernel include file (include/linux/compiler.h) 裡它們是這樣定義的:

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

這個意思是怎樣呢? 用 google 找了一下, 原來是說當 define likely 時, 預期判斷式的結果會是 x, 這樣 compiler 會把 x 為 true 的內容翻議之後放的比較近一點, 如此一來 instruction cache hit rate 會提高一點; 而 unlikely 就是預期 x 不為真, 這樣的話 compiler 就會把不為 true 的內容擺的比較近一點.

直接看例子比較快, 如以下的 c code:

int main(void)
{
int x, y, z;

x=1;
if (x)
{
y=x+1;
printf("Y: %d\n", y);
}
else
{
y=x+2;
printf("Y: %d\n", y);
}

printf("X: %d, Y: %x\n", x, y);

return 0;

}


我用 arm compiler 去 compile 後看到的 assembly code:


main.o: file format elf32-littlearm

Disassembly of section .text:

00000000
:
main():
0: e92d4030 stmdb sp!, {r4, r5, lr}
4: e3a04001 mov r4, #1 ; 0x1
8: e0845004 add r5, r4, r4
c: e1a01005 mov r1, r5
10: e59f0018 ldr r0, [pc, #24] ; 30 <.text+0x30>
14: ebfffffe bl 0
18: e1a01004 mov r1, r4
1c: e1a02005 mov r2, r5
20: e59f000c ldr r0, [pc, #12] ; 34 <.text+0x34>
24: ebfffffe bl 0
28: e3a00000 mov r0, #0 ; 0x0
2c: e8bd8030 ldmia sp!, {r4, r5, pc}
30: 00000000 andeq r0, r0, r0
34: 00000008 andeq r0, r0, r8

unlikely:


main3.o: file format elf32-littlearm

Disassembly of section .text:

00000000
:
main():
0: e92d4010 stmdb sp!, {r4, lr}
4: e3a00001 mov r0, #1 ; 0x1
8: ebfffffe bl 0
c: e3a04002 mov r4, #2 ; 0x2
10: e3500000 cmp r0, #0 ; 0x0
14: e1a01004 mov r1, r4
18: 03a04003 moveq r4, #3 ; 0x3
1c: 01a01004 moveq r1, r4
20: e59f001c ldr r0, [pc, #28] ; 44 <.text+0x44>
24: 059f0018 ldreq r0, [pc, #24] ; 44 <.text+0x44>
28: ebfffffe bl 0
2c: e1a02004 mov r2, r4
30: e3a01001 mov r1, #1 ; 0x1
34: e59f000c ldr r0, [pc, #12] ; 48 <.text+0x48>
38: ebfffffe bl 0
3c: e3a00000 mov r0, #0 ; 0x0
40: e8bd8010 ldmia sp!, {r4, pc}
44: 00000000 andeq r0, r0, r0
48: 00000008 andeq r0, r0, r8

likely:


main2.o: file format elf32-littlearm

Disassembly of section .text:

00000000
:
main():
0: e92d4010 stmdb sp!, {r4, lr}
4: e3a00001 mov r0, #1 ; 0x1
8: ebfffffe bl 0
c: e3a04002 mov r4, #2 ; 0x2
10: e3500000 cmp r0, #0 ; 0x0
14: e1a01004 mov r1, r4
18: 03a04003 moveq r4, #3 ; 0x3
1c: 01a01004 moveq r1, r4
20: e59f001c ldr r0, [pc, #28] ; 44 <.text+0x44>
24: 059f0018 ldreq r0, [pc, #24] ; 44 <.text+0x44>
28: ebfffffe bl 0
2c: e1a02004 mov r2, r4
30: e3a01001 mov r1, #1 ; 0x1
34: e59f000c ldr r0, [pc, #12] ; 48 <.text+0x48>
38: ebfffffe bl 0
3c: e3a00000 mov r0, #0 ; 0x0
40: e8bd8010 ldmia sp!, {r4, pc}
44: 00000000 andeq r0, r0, r0
48: 00000008 andeq r0, r0, r8

怪怪的, 不管是 likely 或 unlikely 翻出來的 code 幾乎一樣, 後來換用 MIPS 跟 PowerPC compiler 都依樣... 看來 embedded system 的 compiler optimization 都沒做好 !?

荒漠甘泉 20080328

『等到抬普天下主耶和華約櫃的祭司把腳站在約但河水裏,約但河的水,就是從上往下流的水,必然斷絕,立起成壘。』(書三章十三節)

勇敢的利未人!誰能不佩服他們的膽量--抬了約櫃伸腳到還未分開的水中去。神也一無其他的勉勵和應許,只等待看他們的信心。神重視信心,尤其是不憑理由的信心,你可以推想當初許多百姓看見這些利未人抬了約櫃下水,他們一定發急地說:『要是我,決不是這樣作無謂的犧牲!冒這樣大的險!可惜,他們和約櫃就要被約但河的急流沖出去了!』可是,並不是這樣;『抬耶和華約櫃的祭司在約但河中的乾地上站定』(十七節)。我們不要小看信心,我們的信心能幫助神成功祂的計畫。『……來幫助耶和華』(士五章二十三節)

信心能幫助神。信心能叫神封住獅子的口,能叫神使火失其利害。這並非說:沒有人的信心,神就失去祂的全能,而不能作甚麼;祂仍能,可是祂即使作了,祂得不著榮耀。祂若封住獅子的口,只叫牠餓一天罷了;祂使火失其利害,只使宇宙中間多了一件反常的事罷
了。並沒有甚麼意思。神根據人的信心這麼作了,纔能從大利烏與尼布甲尼撒口中得到稱頌。,信心榮耀神,所以神也重視信心。

真信心有了神的應許就滿足了--他肯讓神揀選神看為適當的時候來完成祂的應許,不管那時候有多久。

今天在恩典下同作利未人的哪,讓我們憑著無理由的信心,抬起神的應許來,不要想我們抬的的神的棺材。這是永活之神的約櫃呀!讓我們一面唱歌,一面下水罷!--強卜奈斯(Thomas Champness)

勇敢的,精神是使徒時代教會的特點。如果我們想為神作大事業,想從神得到大使命,我們必須有勇敢的信心。如果我們與超然的神攘觸,向祂要人力所不能得到的東西,我告訴你:拿得多比拿得少還容易;大膽地站在應許上比膽怯地攀住海岸來得容易。

讓我們相信:在神凡事都能;並且,肯相信:在信的人,凡事都能!

讓我們今天來替神作大事業;相信祂能力是能完成一切的。--譯自在地上的天上生活 (DaysofHeaven upon Earth)