多核下寫高性能并行程序
什么樣的程序執(zhí)行效率高?
程序的數(shù)據(jù)和指令都在cache中,沒(méi)有cache miss出現(xiàn)。
所以如何讓并行程序性能高基本可以演變成 如何減少cache miss?
尤其是多核下,并行程序cache的問(wèn)題已經(jīng)無(wú)法回避了,否則并行的效率還沒(méi)有一個(gè)線程高。
寫程序的時(shí)候MESI協(xié)議要時(shí)刻浮現(xiàn)在眼前。
借用一句歌詞:現(xiàn)在不是從前了,兔子比狐貍狡猾了。
1.絞盡所有的腦汁,避免使用全局變量,尤其是程序運(yùn)行過(guò)程中可能修改的變量。所有線程只讀的變量可以放松一丁點(diǎn)兒要求。
2.per thread per core。每個(gè)core運(yùn)行一個(gè)線程,每個(gè)線程運(yùn)行在一個(gè)cpu core上。
3.Keep data structures ?per core。每個(gè)core僅僅修改自己的數(shù)據(jù)結(jié)構(gòu)。
4.Keep data structures cache alignment。保證結(jié)構(gòu)體定義的時(shí)候cache line對(duì)齊??梢宰约禾砑觩ad,也可以用gcc提供的__attribute__。
5.避免false sharing。定義數(shù)據(jù)結(jié)構(gòu)的時(shí)候不能這么搞: int num[CPU_NUMS],這樣在for循環(huán)中對(duì)num[i]++的時(shí)候就會(huì)造成false sharing。這也是為什么結(jié)構(gòu)體定義要cache line對(duì)齊。
6. Lock-free data structures。鎖的代價(jià)是巨大的,搞不好還會(huì)死鎖,多核間通信用lock-free fifo。
7.cpu affinity。線程創(chuàng)建后立即綁定到具體的core上,然后再 進(jìn)行分配內(nèi)存,保證內(nèi)存分配在自己的領(lǐng)土這邊。
8.分支預(yù)測(cè)。使用gcc提供的likely和unlikely。
9.公共子表達(dá)式消除。一個(gè)函數(shù)中如果多次用到同一個(gè)表達(dá)式,可以開始的時(shí)候定義一個(gè)指針。
10.循環(huán)中消除指針引用。比如下面這樣:
for(i=0; i< 1000; i++)
{
? ? *dest++;
}
可以先定義一個(gè)局部變量進(jìn)行累加,最后再把局部變量賦值給指針。
11.X86平臺(tái)intel提供了很多的sse指令,尤其是在字符串的搜索和查找方面。
12.多用perf tool。
暫時(shí)想到的先記錄下來(lái),找個(gè)時(shí)間給出具體的代碼逐條舉例說(shuō)明一下。