2009-06-28 48 views
11

英特爾的32位處理器(例如Pentium)具有64位寬的數據總線,因此每次訪問可獲取8個字節。基於此,我假設這些處理器在地址總線上發出的物理地址始終爲8的整數倍。32位英特爾處理器上的內存對齊

首先,這個結論是否正確?其次,如果它是正確的,那麼應該在8字節邊界上對齊數據結構成員。但我已經看到人們在這些處理器上使用4字節對齊方式。

他們怎麼能這樣做是正當的?

+1

我不知道這個問題是什麼意思,但是我對這與編程有關,以及這可能如何影響我感興趣。我在哪裏可以讀到這種低級別類型的基本介紹? – 2009-06-28 10:38:53

+4

請參閱「每個程序員應該知道什麼關於內存」:http://people.redhat.com/drepper/cpumemory.pdf – Crashworks 2009-06-28 10:56:24

+1

如何從「請求的讀取總是8的倍數」到「您的數據始終應該始於一個8字節的邊界「?我沒有看到這些之間的邏輯連接。只要數據不交叉* 8字節的邊界,我們就很好,是不是? – jalf 2009-06-28 11:59:35

回答

14

通常的經驗法則(直接來自英特爾和AMD的優化手冊)是每個數據類型應該按照自己的大小進行對齊。 int32應該在32位邊界上對齊,在64位邊界上則爲int64,依此類推。字符在任何地方都適合。

另一個經驗法則當然是「編譯器已經被告知對齊要求」。您不必擔心它,因爲編譯器知道添加正確的填充和偏移量以允許有效地訪問數據。

唯一的例外是使用SIMD指令時,您必須在大多數編譯器上手動確保對齊。

其次,如果它是正確的,那麼一個 應 8字節邊界對齊數據結構成員。但我看到 人使用4字節對齊 代替這些處理器。

我看不出有什麼不同。 CPU可以簡單地爲包含這4個字節的64位塊發出讀取。這意味着它可以在請求的數據之前或之後獲得4個額外的字節。但在這兩種情況下,它只需要一次讀取。 32位寬數據的32位對齊確保它不會跨越64位邊界。

6

物理總線是64位寬... 8的倍數 - >是

然而,有兩個因素需要考慮:

  1. 有的x86指令集是字節尋址。有些是32位對齊(這就是爲什麼你有4個字節的東西)。但沒有(核心)指令是64位對齊的。 CPU可以處理未對齊的數據訪問。
  2. 如果你關心性能,你應該考慮緩存行,而不是主內存。高速緩存線要寬得多。
0

對於隨機訪問和只要數據沒有錯位(例如跨越邊界),我認爲這不重要;數據中的正確地址和偏移量可以通過硬件中的簡單AND結構來找到。當一個讀訪問不足以獲得一個值時,它會變慢。這也是爲什麼編譯器通常會將小值(字節等)放在一起的原因,因爲它們不必位於特定的偏移處;短路應該在偶數地址上,32位在4字節地址和64位在8字節地址上。

請注意,如果您有緩存的involed和線性數據訪問,事情會有所不同。

2

這樣做是有道理的,因爲改爲8字節對齊將構成ABI更改,並且邊際性能改進不值得麻煩。

正如其他人所說,緩存線很重要。實際存儲器總線上的所有訪問都是根據高速緩存行(x86上的64字節,IIRC)進行的。請參閱已經提到的「每個程序員需要了解的內存」文檔。所以實際的內存流量是64字節對齊的。

1

您引用的64位總線饋送高速緩存。作爲一個CPU,總是讀寫整個緩存行。高速緩存行的大小始終是8的倍數,並且其物理地址確實與8字節偏移對齊。

Cache-to-register傳輸不使用外部數據總線,因此該總線的寬度是不相關的。