記憶體對其加速cpu訪問速度原理

2021-06-28 00:08:44 字數 1482 閱讀 2393



記憶體對齊問題是每乙個c程式設計師都應該考慮過的問題,c編譯器的規則明確規定了對齊問題,就是乙個struct中按照最長的型別對齊,比如考慮下面的結構體:

struct abc

char a;

int b;

char c;

在32位x86機器上它的大小是多少呢?是12,為什麼呢?因為該結構體中最長的型別是int,因此需要按照4位元組對齊,因此a和c後面都要pad進去3個無辜的位元組,是不是太浪費了呢?是的,但是如果該結構體不是非這樣設計不可(如果是網路協議之類的既定協議就不能隨意更換,這涉及協議設計問題,不深談),你完全可以將b和c對換一下位置,這樣的話,大小將會成為8,能否再節省一些呢?可以,那就是用pack偽指令取消編譯器的記憶體對齊,但是代價是效率更低以及更不安全,首先看一下為何效率更低。

32位cpu上,資料匯流排是32位的,一次訪問32位的資料,如果不對齊,那麼考慮cpu訪問完a然後訪問b的情況,訪問完a,一次訪問了a開始的32位4位元組的資料,此時僅有開始的8個位元組是有效的(以下不考慮大小端),後面的3個位元組被丟棄,然後訪問b,繼續向前推進制址匯流排,就是位址為a的位址加4,那麼得到的是4位元組b的最後乙個位元組和c然後跟著乙個無關的兩個位元組的結構外的資料,為了得到b的前三個位元組,位址必須退回到a的位址,然後拋棄a從而得到後面的三個位元組,或者直接退回到a的位址的下乙個位址,但是這種情況下直接就可以得到b,前面得到的b的最後乙個位元組就沒有用了,不管怎樣最少需要三次訪存,即使cpu可以精確到正好將位址回退到b的位址,回退匯流排也沒有順序推進匯流排高效。如果是4位元組對齊的,那麼在訪問完a後,直接訪問下乙個4位元組就可以了,這就體現了高效性。

很多人都認為寫比讀更麻煩,對於cpu而言是這樣嗎?cpu要想讀乙個資料,第一步必須將位址匯流排設定好,然後在下乙個週期才能在資料匯流排得到資料,然而對於寫操作,cpu可以一步完成,直接將位址放到位址匯流排,並且將資料置於資料匯流排就可以了,乙個週期就可以完成,因此對於cpu而言,寫比讀更容易。以上是乙個無關緊要的話題,現在考慮多cpu的情況,多個cpu連線的是同乙個位址匯流排以及同乙個資料匯流排,也就是說記憶體是單進單出的,至於怎麼路由到多個cpu並不是儲存器本身的問題,一般而言乙個匯流排週期只能由乙個cpu控制匯流排,如果資料沒有對齊,那麼由於需要額外的很多次匯流排操作,那麼就會出現一種情況,即乙個cpu操作完了匯流排讀到了4個位元組中的1個位元組,還剩下3個位元組沒有讀,此時其它cpu控制了匯流排,在剩下的3個位元組的位址處寫入了資料,那麼等到第乙個cpu再次控制匯流排時就會得到錯誤的資料,雖然這件事事實上不會發生,但是必然擁有制止這件事發生的措施,既然有了措施就一定有了開銷,如果資料是對齊的,那麼這種開銷就不會有,簡單的說也是提高了效率。

因此很多32位的cpu直接禁掉了位址匯流排的低兩位,所以該類cpu只能訪問4位元組對齊的資料,另一些cpu會捕獲訪問不對齊的資料,這裡有乙個很古老的話題,就是為何乙個位元組是8位,因為老的成型的cpu的匯流排寬度是8位!實際上當今的cpu中這類對齊優化已經沒有純粹的優化意義了,因為區域性原理連同cpu的cache會掩蓋對齊得到的優化。cpu的優化原則是對於長度為n的資料的位址被分配到n的整數倍,這樣就會在訪問完該資料後順序的到達下乙個資料而不需要切割操作。

CPU訪問記憶體

1.cpu匯流排週期 匯流排週期,包含若干個時鐘週期,計算機是在時鐘脈衝下乙個節拍乙個節拍的工作。看下面這張圖,我們可以很好的理解為什麼要時鐘了 這個圖我們可以認為是乙個基本的讀記憶體資料的匯流排週期 在t1時鐘週期期間,cpu往匯流排上發位址資訊,以指出要定址的儲存單元 在t2時鐘周期間,撤銷位址...

關於記憶體對其問題 三

第一種情況 struct bbb long num 4bytes char name 4 bytes short int data 2 bytes char ha 1 byte short ba 5 10 bytes sizeof bbb 24bytes 理由 1.很容易知道bbb的記憶體對齊數是4...

pragma pack n 與記憶體對其問題

title pragma pack n 與記憶體對其問題 date 2016 06 08 15 32 11 categories c tags c c 記憶體對齊 pragma pack 作用 遮蔽掉編譯器為變數設定的預設的對其方式,設定自己的對其方式 而 pragma pack n 表示設定變數以...