快取記憶體 (Cache Memories)

Overview Table

主題 核心內容 書頁
通用快取組織 (S, E, B, m) 四元組描述;C=S×E×B p.651-653
位址分割 m 位元位址 → tag (t) + set index (s) + block offset (b),t=m(s+b) p.651-652
Direct-mapped (E=1) 每 set 恰一 line;三步驟:set selection → line matching → word selection p.653-657
Conflict miss / Thrashing 2 的冪次大小陣列易映射到同一 set 造成互相驅逐;以 padding 修正 p.658-660
Set associative (1<E<C/B) 每 set 多條 line,需平行比對多個 tag;替換策略 LRU/LFU/隨機 p.660-662
Fully associative (E=C/B) 只有一個 set,位址無 set index 欄位;僅適合小快取(如 TLB) p.662-664
寫入策略 write hit: write-through vs write-back;write miss: write-allocate vs no-write-allocate p.666-667
真實快取階層 i-cache / d-cache / unified cache;Intel Core i7 三層結構 p.667-668
效能參數 miss rate、hit rate、hit time、miss penalty;C、B、E、寫入策略的取捨 p.667-669

6.4 快取記憶體的由來 (p.650-651)

早期系統的記憶體階層只有三層:CPU registersmain memorydisk。隨著 CPU 與主記憶體速度差距擴大,設計者在 register file 與主記憶體之間插入小型 SRAM 快取:

CPU chip
+---------------------------------+
|  Register file                  |
|  +-------+        +-----+       |
|  | Cache |<------>| ALU |       |
|  | mems  |        +-----+       |
|  +-------+                      |
|      |                          |    System bus      Memory bus
|  +---------------+              |   +------------+   +--------+
|  | Bus interface |<-------------+-->| I/O bridge |<->|  Main  |
|  +---------------+              |   +------------+   | memory |
+---------------------------------+                    +--------+
本節討論假設 CPU 與主記憶體之間只有單一 L1 快取的簡化模型;真實系統(見 6.4.6)有多層、多核、指令/資料分離的變化,但原理相同。

6.4.1 通用快取組織 (S, E, B, m) (p.651-653)

位址有 m 位元,共 M=2m 個位址。快取組織成 S=2scache set;每個 set 有 Ecache line;每條 line 含一個 B=2b bytes 的 data block、1 個 valid bit(標示此 line 是否含有意義資訊)、t=m(b+s)tag bits(唯一識別存放在該 line 的區塊)。

位址分割 (m 位元):
 m-1                                    0
 +-----------+-------------+------------+
 |  t bits   |   s bits    |   b bits   |
 |   Tag     |  Set index  | Blk offset |
 +-----------+-------------+------------+

快取結構:
            +-------+-----+----------------+
  Set 0:    | Valid | Tag | 0 | 1 |...|B-1 |  \
            +-------+-----+----------------+   E lines
            | Valid | Tag | 0 | 1 |...|B-1 |  /  per set
            +-------+-----+----------------+
  Set 1:    |  ...                         |
            +------------------------------+     S = 2^s sets
  Set S-1:  |  ...                         |
            +------------------------------+

參數速查表 (Figure 6.26, p.653)

參數 意義
S=2s set 數量
E 每 set 的 line 數
B=2b block 大小 (bytes)
m=log2M 實體位址位元數
M=2m 位址總數(衍生)
s=log2S set index 位元數(衍生)
b=log2B block offset 位元數(衍生)
t=m(s+b) tag 位元數(衍生)
C=B×E×S 快取容量(不含 valid/tag overhead)

6.4.2 Direct-Mapped Cache (E=1) (p.653-660)

每個 set 恰好一條 line,是最容易實作與理解的類別。判定 hit/miss 並取出字組的流程分三步:

CPU 送出位址 A
      |
      v
(1) Set selection: 取中間 s bits 當 unsigned index 選 set
      |
      v
(2) Line matching: valid bit == 1 且 line tag == 位址 tag ?
      |                       |
     Yes                      No
      |                       v
      v                  Cache miss --> 向下層取 block,存入該 set
(3) Word selection:            (E=1 時替換策略 trivial:直接覆蓋現有 line)
    block offset 指出字組在 block 內的起始 byte --> 回傳給 CPU

實例模擬:(S,E,B,m)=(4,1,2,4) (p.655-657)

4 組、每組 1 line、每 block 2 bytes、4 位元位址(假設字組為 1 byte)。列舉整個位址空間並分割位元後可觀察到:

讀取序列示範(初始所有 valid bit = 0):

步驟 讀位址 結果 原因
1 0 miss set 0 valid=0;載入 block 0,回傳 m[0]
2 1 hit 同 block,回傳 m[1],快取狀態不變
3 13 miss set 2 無效;載入 block 6,回傳 m[13]
4 8 miss set 0 valid=1 但 tag 不符;block 4 取代 block 0
5 0 miss (conflict) block 0 剛在步驟 4 被驅逐,需重新載入

Conflict Miss 與 Thrashing (p.658-660)

Conflict miss:快取整體空間足夠,卻因交替引用映射到同一 set 的 block 而反覆互相驅逐。Thrashing 泛指快取反覆載入又驅逐同一批 block 的情形。

典型案例 dotprod:float x[8]y[8] 連續放置(x 從位址 0、y 從 32),block 16 bytes、2 sets(C = 32 bytes)時,每個 x[i]y[i] 映射到相同 set——第一次讀 x[0] miss 載入 x[0]-x[3],接著讀 y[0] miss 又把它覆蓋掉,如此往復,每次引用都是 conflict miss。

為何用中間位元當 set index?(Aside, p.659)

若用高位位元做 index,連續相鄰的 memory block 會映射到同一個 set——順序掃描陣列時,快取任一時刻只能保存約一個 block 大小的陣列內容,利用率極差。用中間位元則相鄰 block 必落在不同 set,快取可同時保存一整個 C 大小的連續陣列區段。

「空間局部性好 → 命中率高」是一般化敘述,例外正是上述 conflict miss/thrashing:局部性再好,只要 block 映射衝突就會全 miss。局部性背景見 06-Memory-Hierarchy/02-Locality-and-Memory-Hierarchy

6.4.3 Set Associative Cache (1<E<C/B) (p.660-662)

Direct-mapped 的 conflict miss 源自「每 set 恰一 line」的限制;set associative cache 放寬此限制,每 set 持有多條 line。每 set 有 E 條 line 者稱 E-way set associative cache

Miss 時的替換 (line replacement):

6.4.4 Fully Associative Cache (E=C/B) (p.662-664)

整個快取只有單一 set,包含全部 line。

Fully associative 位址分割(沒有 set index 欄位):
 m-1                          0
 +---------------+------------+
 |    Tag        | Blk offset |
 +---------------+------------+

三種組織比較

類別 E 值 set 數 位址欄位 line matching 成本 conflict miss
Direct-mapped E=1 S=C/B tag + index + offset 只比對 1 條 line,最快 最易發生
E-way set associative 1<E<C/B S=C/(EB) tag + index + offset 平行比對 E 條 較少
Fully associative E=C/B S=1 tag + offset(無 index) 平行比對全部 line,昂貴 無(僅 capacity)
Practice 6.12-6.16 (p.664-666) 的典型題型:給 13-bit 位址、2-way、B=4、S=8 的快取內容表,要求切出 CO/CI/CT 欄位並判斷 hit/miss 與回傳 byte。切法:低 2 bits = CO,次 3 bits = CI,高 8 bits = CT。

6.4.5 寫入的議題 (p.666-667)

讀取單純:hit 直接回傳;miss 則向下層抓 block、存入某條 line(可能驅逐 valid line)、再回傳。寫入則有兩個獨立的決策點:

決策點 策略 作法 優點 缺點
write hit write-through 立即把 w 的 cache block 寫到下一層 簡單 每次寫入都造成 bus traffic
write hit write-back 延遲到該 block 被替換演算法驅逐時才寫回下一層 利用局部性,大幅減少匯流排流量 較複雜;每條 line 需 dirty bit 記錄 block 是否被修改
write miss write-allocate 先把對應 block 從下層載入快取,再更新快取中的 block 利用寫入的空間局部性 每次 miss 都要從下層搬一個 block
write miss no-write-allocate 繞過快取,直接把字組寫到下一層 避免搬移 不利後續存取
給程式設計者的心智模型 (p.667):一律假設 write-back + write-allocate 快取。理由:(1) 符合現代趨勢;(2) 與讀取的處理方式對稱——兩者都在利用局部性。因此只需在高層次寫出時間/空間局部性好的程式,不必針對特定記憶體系統最佳化。

6.4.6 真實快取階層剖析:Intel Core i7 (p.667-668)

快取不只放程式資料,也放指令:

現代處理器採分離的 i-cache 與 d-cache,理由:CPU 可同時讀一個指令字與一個資料字;兩者可針對不同存取模式分別最佳化(不同 block size、associativity、容量);且資料存取不會與指令存取互造 conflict miss——代價是可能增加 capacity miss

Processor package (Core i7, 4 cores)
+------------------------------------------------------+
| Core 0                            Core 3              |
| +------+                          +------+            |
| | Regs |                          | Regs |            |
| +------+                          +------+            |
| +---------+ +---------+    ...    +---------+ +-----+ |
| |L1 dcache| |L1 icache|           |L1 dcache| |L1 ic| |
| +---------+ +---------+           +---------+ +-----+ |
| +--------------------+            +------------------+|
| |  L2 unified cache  |            | L2 unified cache ||
| +--------------------+            +------------------+|
| +--------------------------------------------------+ |
| |      L3 unified cache (shared by all cores)       | |
| +--------------------------------------------------+ |
+------------------------------------------------------+
                          |
                    Main memory
Cache 存取時間 (cycles) C E (assoc.) B S
L1 i-cache 4 32 KB 8 64 B 64
L1 d-cache 4 32 KB 8 64 B 64
L2 unified 10 256 KB 8 64 B 512
L3 unified 40-75 8 MB 16 64 B 8,192

6.4.7 快取參數對效能的影響 (p.667-669)

效能量測指標:

各參數的質性取捨(精確最佳化需在真實 benchmark 上大量模擬,超出本書範圍):

參數/策略 好處 代價
加大 cache size C hit rate 上升 大記憶體難做快 → hit time 上升(這解釋了為何 L1 < L2 < L3)
加大 block size B 利用空間局部性 → hit rate 上升 C 固定時 line 數變少,傷害時間局部性強於空間局部性的程式;miss penalty 上升(傳輸時間變長)。現代系統折衷為 64 bytes
提高 associativity E 降低因 conflict miss 造成 thrashing 的風險 實作昂貴且難快:更多 tag bits、額外 LRU 狀態位元、更多控制邏輯;hit time 上升,選 victim line 更複雜使 miss penalty 也上升
write-through 較簡單;可配獨立運作的 write buffer;read miss 較便宜(不觸發記憶體寫入) 每寫必傳,bus traffic 大
write-back 傳輸次數少,把記憶體頻寬留給做 DMA 的 I/O 裝置;越下層(傳輸時間越長)越划算 較複雜(dirty bit)

Exam/Test Patterns

情境 / 關鍵字 答案
(m,C,B,E)S,t,s,b(Practice 6.9 型) S=C/(EB);b=log2B;s=log2S;t=msb
給位址 + 快取內容表,問 hit/miss 與回傳 byte(Practice 6.12-6.15 型) 位址由低到高切 CO(b bits)、CI(s bits)、CT(其餘 t bits);到 set CI 找 valid=1 且 tag=CT 的 line;hit 取 byte CO,miss 無回傳值
「valid=1 但 tag 不符」 miss(且會觸發替換);hit 需 valid 與 tag 兩條件同時成立
交替存取兩個 2 的冪次大小的陣列、每次都 miss conflict miss / thrashing;解法:陣列尾端加 B bytes padding 錯開 set 映射
為何 set index 用中間位元而非高位位元? 高位索引使連續相鄰 block 落在同一 set,順序掃描時快取只能存一個 block;中間位元讓相鄰 block 分散到不同 set,可存整個 C 大小區段
位址欄位只有 tag 與 offset、沒有 set index fully associative cache(E=C/B,單一 set)
哪種快取組織適合 TLB? fully associative(小、需平行比對 tag、無 conflict miss)
write hit 後何時更新下層? write-through 立即;write-back 等被驅逐時(需 dirty bit)
write miss 是否把 block 載入快取? write-allocate 載入後更新;no-write-allocate 直接寫下層
典型寫入策略配對 write-through ↔ no-write-allocate;write-back ↔ write-allocate
程式設計者應假設哪種寫入模型? write-back + write-allocate(符合趨勢、與讀取對稱、鼓勵寫局部性好的程式)
miss rate / hit rate 計算 miss rate = #misses / #references;hit rate = 1 − miss rate
加大 B 對 miss penalty 的影響 上升(block 傳輸時間變長)
i-cache / d-cache 分離的利與弊 可同時取指令與資料、各自最佳化、消除指令與資料間 conflict miss;但可能增加 capacity miss
L1 為何比 L2 小、L2 比 L3 小? 大快取難做快;小容量換低 hit time
提高 E 降低哪種 miss? conflict miss(對 capacity miss 無助益)