淺談數據對齊對CPU效率的影響(轉)

最近看到有關數據對齊的內容,每次都會提到對CPU的影響,但到底對CPU有什麼影響?是怎樣影響的?大都略過,沒有詳細的介紹,自己google了一下,找到了一些“蛛絲馬跡”,在這兒與大家分享一下。

      關於內存對齊的中文文章多在介紹對齊的'法則',比如爲什麼sizeof(T)和我們估計的T的大小有出入呢等等,而對於內存對齊的本質少有介紹,我在Google上搜索了一陣後,在IBM開發社區上發現一篇叫'Data alignment: Straighten up and fly right '的文章,其中就有我想知道的關於'內存對齊背後的故事',下面的很多內容都是來自那篇文章的。

      很多書籍中都講到:內存可以看成一個byte數組,我們通過編程語言提供的工具對這個'大數組'中的每個元素進行讀寫,比如在C中我們可以用指針一次讀寫 一個或者更多個字節,這是我們一般程序員眼中的內存樣子。但是從機器角度更具體的說從CPU角度看呢,CPU發出的指令是一個字節一個字節讀寫內存嗎?答 案是'否'。CPU是按照'塊(chunk)'來讀寫內存的,塊的大小可以是2bytes, 4bytes, 8bytes, 16bytes甚至是32bytes. 這個CPU訪問內存採用的塊的大小,我們可以稱爲'內存訪問粒度'。

程序員眼中的內存樣子:

---------------------------------
| | | | | | | | | | | | | | | | |
---------------------------------
0 1 2 3 4 5 6 7 8 9 A B C D E F  (地址)

CPU眼中的內存樣子:(以粒度=4爲例)
---------------------------------------------
| | | | |   | | | | |   | | | | |   | | | | |
---------------------------------------------
0 1 2 3     4 5 6 7     8 9 A B     C D E F  (地址)

有了上面的概念,我們來看看粒度對CPU訪問內存的影響。

假設這裏我們需要的數據分別存儲於地址0和地址1起始的連續4個字節的存儲器中,我們目的是分別讀取這些數據到一個4字節的寄存器中,

      如果'內存訪問粒度'爲1,CPU從地址0開始讀取,需要4次訪問才能將4個字節讀到寄存器中;
同樣如果'內存訪問粒度'爲1,CPU從地址1開始讀取,也需要4次訪問才能將4個字節讀到寄存器中;而且對於這種理想中的''內存訪問粒度'爲1的CPU,所有地址都是'aligned address'。

      如果'內存訪問粒度'爲2,CPU從地址0開始讀取,需要2次訪問才能將4個字節讀到寄存器中;每次訪存都能從'aligned address'起始。
如 果'內存訪問粒度'爲2,CPU從地址1開始讀取,相當於內存中數據分佈在1,2,3,4三個地址上,由於1不是'aligned address',所以這時CPU要做些其他工作,由於這四個字節分步在三個chunk上,所以CPU需要進行三次訪存操作,第一次讀取chunk1(即 地址0,1上兩個字節,而且僅僅地址1上的數據有用),第二次讀取chunk2(即地址2,3上兩個字節,這兩個地址上的數據都有用),最後一次讀取 chunk3(即地址5,6上兩個字節,而且僅僅地址5上的數據有用),最後CPU會將讀取的有用的數據做merge操作,然後放到寄存器中。

同理可以推斷如果'內存訪問粒度'爲4,那麼從地址1開始讀取,需要2次訪問,訪問後得到的結果merge後放到寄存器中。

      是不是所有的CPU都會幫你這麼做呢,當然不是。有些廠商的CPU發現你訪問unaligned address,就會報錯,或者打開調試器或者dump core,比如sun sparc solaris絕對不會容忍你訪問unaligned address,都會以一個core結束你的程序的執行。所以一般編譯器都會在編譯時做相應的優化以保證程序運行時所有數據都是存儲在'aligned address'上的,這就是內存對齊的由來。

我們可以指定按照何種粒度訪問特定內存塊兒:其中void *T爲指向特定內存塊的地址指針
char *p = (char*)T;每次操作一個字節
short *p = (short*)T;每次操作兩個字節
int *p = (int*)T;每次操作4個字節
以此類推。

      在'Data alignment: Straighten up and fly right'這篇文章中作者還得出一個結論那就是:"如果訪問的地址是unaligned的,那麼採用大粒度訪問內存有可能比小粒度訪問內存還要慢"。

      最後感謝Tony Bai 的分享。

版權聲明 :轉載時請以超鏈接形式標明文章原始出處和作者信息及本聲明
http://bigwhite.blogbus.com/logs/3990258.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章