多核程式設計中的偽共享問題及其對策
注:本文主要內容摘自筆者所著的《多核計算與程式設計》一書,略有修改,後續還會繼續發布系列文章,如有需要,可以考慮將一下位址加入到您的瀏覽器收藏夾中:
偽共享問題在《多核程式設計技術-通過軟體多執行緒提公升效能》一書中有詳細講解,它是由於cpu cache機制造成的,cpu讀取cache時是以行為單位讀取的,如果兩個硬體執行緒的兩塊不同記憶體位於同一cache行裡,那麼當兩個硬體執行緒同時在對各自的記憶體進行寫操作時,將會造成兩個硬體執行緒寫同一cache行的問題,它會引起競爭,就像在桌球比賽一樣,效率將成百倍的下降。
在單核系統中,偽共享問題是不存在的,因為同一時刻只有乙個硬體執行緒在執行,不存在同時寫同一cache行的問題。
偽共享問題在實際情況中是經常可以碰到的,比如兩個執行緒同時寫乙個陣列的相鄰部分,或者寫兩塊相鄰的記憶體,這些都有可能造成偽共享問題。
對於分配的記憶體,可以採取一定的記憶體分配演算法使各塊記憶體不在同一cache行裡,但對於陣列或變數的訪問,就必須要由程式設計師在設計時進行避免偽共享問題。
要解決偽共享問題,首先必須知道給定的記憶體中,那塊區域會處於同一cache行內,intel的系統中,有乙個簡單的演算法可以得到一塊記憶體中對應的cache行首位址,即每個cache行首位址都是cache行大小的整數倍。
比如一塊記憶體大小為60位元組,首位址為0x0012ff52,由於0x0012ff52除以64以後餘數為0x12,因此這個位址不是cache行的首位址。在這個位址之前的cache行首位址為0x0012ff40,在這個位址之後的cache行首位址為0x0012ff80。對應的記憶體位於兩塊不同的cache中。如下圖所示:
圖1:cache行對齊示意圖
/** 計算給定位址之後的第0個cache行首位址
如果給定位址剛好為乙個cache行首位址,那麼計算結果等於它自身
@param void *paddr - 給定的位址
@return void * - 返回給定位址之後的第0個cache行首位址
*/void *getcachealignedaddr(void *paddr)
取到了cache行首位址後,就可以區分出兩塊記憶體是否在同一cache行中了,對避免偽共享問題就有了很大的幫助。
/** 計算給定位址之後的cache行首位址
@param void *paddr - 給定的位址
@return void * - 返回給定位址之後的cache行首位址
*/void *getnextcachealignedaddr(void *paddr)
當然,偽共享問題在許多地方都會出現,各種地方的處理方法各有不同,但是所有的方法都需要用到上面講過的取cache行首位址的方法。
偽共享問題遇得較多的地方是處理陣列型別的資料,其次是記憶體管理上要從源頭上將偽共享問題減少。後續的多核系列文章中,還會有文章詳細講解具體的偽共享處理例項。
多核程式設計的幾個難題及其應對策略(難題一)
多核程式設計的幾個難題及其應對策略 難題一 多核程式設計中的負載平衡難題 多核程式設計中的鎖競爭難題 openmp並行程式設計 二 openmp並行程式設計 一 雙核cpu上的快速排序效率 隨著多核cpu的出世,多核程式設計方面的問題將擺上了程式設計師的日程,有許多老的程式設計師以為早就有多cpu的...
多核程式設計的幾個難題及其應對策略(難題一)
多核程式設計的幾個難題及其應對策略 難題一 多核程式設計中的負載平衡難題 多核程式設計中的鎖競爭難題 openmp並行程式設計 二 openmp並行程式設計 一 雙核cpu上的快速排序效率 隨著多核cpu的出世,多核程式設計方面的問題將擺上了程式設計師的日程,有許多老的程式設計師以為早就有多cpu的...
多核程式設計的幾個難題及其應對策略(難題一)
多核程式設計的幾個難題及其應對策略 難題一 多核程式設計中的負載平衡難題 多核程式設計中的鎖競爭難題 openmp並行程式設計 二 openmp並行程式設計 一 雙核cpu上的快速排序效率 隨著多核cpu的出世,多核程式設計方面的問題將擺上了程式設計師的日程,有許多老的程式設計師以為早就有多cpu的...