每種數據類型都有一個與之相關的隊列,這個隊列是由處理器架構而非這個語言自己受權的。校準數據元素容許處理器以高效的方式從內存中抓取數據,並由 此提升性能。爲了提供最佳的性能,編譯器試圖保持這種數據元素的隊列。在32位和64位的Linux系統上,英特爾®C++編譯器上使用着的數據類型典型 對齊要求以下:緩存
Data Type數據結構 |
32-bit(bytes)架構 |
64-bit(bytes)ide |
char性能 |
1優化 |
1spa |
short操作系統 |
2設計 |
2指針 |
int |
4 |
4 |
long |
8 |
8 |
float |
4 |
4 |
double |
8 |
8 |
long long |
8 |
8 |
long double |
4 |
16 |
Any pointer |
4 |
8 |
通常狀況下,編譯器會在任何可能的時候都知足這些數據元素的對齊要求。在使用英特爾®C++和Fortran編譯器的狀況下,可使用 -align(C/C++,Fortran語言)編譯器開關來強制或禁止天然對齊規則。對於一般含有不一樣類型的數據元素的結構,編譯器試圖經過在元素之間 插入未使用的存儲來保持的數據元素實現正確對齊。這種技術被稱爲「填充」。此外,編譯器還會以它的最嚴格的對準成員爲基準來對齊整個結構。編譯器也可能會 增長結構的空間大小,必要的時候,編譯器會經過在結構端部添加填充的方式來使其實現成倍的對齊。這就是所謂的「尾填充」。如此一來,填充就醫浪費存儲空間 的代價提高了性能。若是是英特爾®至強融核™協處理器,提供給應用程序可用存儲的數量自己是有限的,這會帶來一個嚴重的問題。
開發者能夠經過給結構元素排序來最小化這種內存浪費,這樣最大/最寬的元素會排在前面,接着是第二寬的,依次排開。下面的這個例子能爲你闡明用結構的空間大小給數據元素排序影響:
結構s1有11個填充字節,以下表所示:
看看下面的結構s2:
這個結構只包含了3個尾填充的字節,以下圖所示:
這樣就節省了內存。所以,僅僅在結構定義中重排數據元素就有可能避免內存浪費。
這種給元素排序的一種例外是,若是你的結構比你的高速緩存線(在因特爾至強融核協處理器上是64個字節)更大的話,一些循環或內核就只能接觸到結構的一部分。在這種狀況下,保持結構的各部分能在內存中一塊兒被接觸到多是有益的,這可能會改善高速緩存局部性。
若是你的結構比高速緩存線更大,而且一些循環和內核只能接觸到結構的一部分的話,你能夠考慮下經過把大結構分解爲多個以單獨的排列存儲的更小的結構。這就潛在地提高了可接觸數據的密度,incident提高了高速緩存的局部性。
你也可使用_decipsec(align)屬性來指導編譯器比用其餘方式更嚴格地對齊數據,這個擴展屬性的語法以下:
C/C++:
_decipsec(align(n))<數據類型聲明>
Fortran:
cDEC$ATRIBUTES ALIGN:n::<數據類型聲明>
這裏的n是要求的隊列,是2的乘冪,在英特爾C++編譯器裏最大爲4096,在英特爾Fortran編譯器裏最大是16384.你可使用這個屬性 爲單個變量,靜態結構或自動存儲持續期間內請求對齊。然而,這就表示,儘管你提升結構的一致性,但這個屬性並不能調整結構內元素的對齊。經過把 _declpsec(align)放在關鍵字struct前面,你就爲僅僅這種類型的對象請求適當的對齊。讓我用下面這個例子來講明個人觀點:
在上述示例中,對字符a2和整數b2的對齊仍然各自保持爲1個字節和4個字節,這是默認的。然而,結構s2的每一個實例都被對齊到32個字節的邊界,正如_declspsec聲明裏描述的那樣。所以,結構s1內部的結構s2目前的每一個實例都將對齊到32個字節的邊界。
咱們還能夠經過動態分配結構s2的排列來進一步擴展這個例子:
這種狀況下,你仍然須要使用_mm_malloc或一個至關於爲指針分配對齊內存的可移植性操做系統接口(POSIX),但經過使用_declspec(align(32)),你就是要爲排列arr1中的每個元素都強制對齊到32個字節。
你也可使用這個數據對齊支持來爲高速緩存線使用最優化提供優點。經過把日常常常在一塊兒使用的小對象彙集到一個結構裏,並強制這個結構從高速緩存線 的起始端分配內存,你就能有效地保證每個對象在須要的時候都能及時地被裝載進高速緩存裏,這樣會有很明顯的性能提高。例如,考慮i和j這兩個被頻繁調用 的變量,他們可能會被分配到不一樣的告訴緩存線上。你能夠像下面這麼來聲明它們:
經過使用這種方式聲明變量,編譯器就能確保這些變量被分配在同一個高速緩存線上。
慧都提供【正版IDE聯合推廣計劃】,各類IDE低至半價出售(截止日期2014/12/31)。另外還有5折限時搶購和免費領iPhone 六、iPad air等好禮!