CPU 以固定寬度(如 8 位元組)讀取記憶體。結構體大小若為存取粒度倍數,單次讀取即可取得完整資料;否則需兩次讀取並拼湊,效能下降。
#pragma pack(1)
struct Unaligned { char a,b,c; uint32_t d; }; // sizeof=7
#pragma pack()
struct Aligned { char a,b,c; uint32_t d; }; // sizeof=8 (編譯器自動填充)
遍歷 10 萬元素陣列 10 萬次:
Unaligned:12.76 秒Aligned:10.50 秒char + uint64_t + uint32_t + uint32_t → 1+7填充+8+4+4=24 位元組。#pragma pack(1) 緊湊佈局,接受速度折損。float sum = 0; for (int i=0; i版本二:展開步長 4,但有資料相依
for (i=0; i版本三:多累加器打破相依
float sum=0, s1=0, s2=0; for (i=0; i提速 2 倍 核心原理
- 現代 CPU 超標量流水線可同時發射多條獨立指令。
- 引入多個暫存變數(
s1,s2)消除循環載入相依,允許指令級平行(ILP)。- 過度展開會增加暫存器壓力導致溢出(Spill),反而降速。
總結檢查清單
- 熱點結構體啟用預設對齊,或手動排序成員(大型優先)減少填充。
- 關鍵迴圈嘗試展開 + 多累加器,測量實際效能再決定保留。
- 嵌入式/記憶體受限環境以空間換時間,謹慎使用對齊與展開。