無阻塞緩存:讓CPU在等內(nèi)存時也不閑著

緩存miss了咋整?傳統(tǒng)做法是CPU干等著,直到數(shù)據(jù)從內(nèi)存回來。無阻塞緩存(Non-blocking Cache)打破了這個規(guī)矩——即使前面有個miss正在處理,后面的請求該干嘛干嘛。這篇聊聊這個技術(shù)的原理、實現(xiàn)和效果。


1. 阻塞緩存的痛點

想象你在餐廳排隊點餐:

  • 前面的人點了個復(fù)雜的套餐(緩存miss,需要等很久)
  • 你只想點杯咖啡(緩存hit,很快)
  • 但阻塞式服務(wù)要求你必須等前面的人拿完餐,才能點你的咖啡

這顯然不合理。CPU里的緩存也是這個道理。

1.1 實際性能損失

1994年,F(xiàn)arkas和Jouppi在DEC Western Research Lab做了個實驗[1]。他們模擬了一個8KB單級緩存,miss penalty 14個周期(90年代初的典型配置)。

結(jié)果發(fā)現(xiàn):SPECINT92基準(zhǔn)測試中,處理器因為緩存miss停頓的時間占總執(zhí)行時間的比例高達(dá)20-30%。這意味著每5條指令就有1條在等內(nèi)存。


2. 無阻塞緩存的兩級優(yōu)化

無阻塞緩存不是單一技術(shù),而是兩個層次的優(yōu)化:

2.1 Hit Under Miss(缺失時命中)

核心思想:前面有個load miss了,后面的load如果hit,照樣可以服務(wù)。

效果:Farkas & Jouppi的測試顯示[2],允許1個hit under miss時:

  • SPECINT92:有效miss penalty降低20%
  • SPECFP92:有效miss penalty降低30%

FP程序提升更明顯,因為科學(xué)計算常有規(guī)律的內(nèi)存訪問模式,miss后緊接著的訪問往往還在緩存里。

2.2 Miss Under Miss(缺失時缺失)

核心思想:允許同時發(fā)出多個內(nèi)存請求,重疊它們的延遲。

這需要內(nèi)存系統(tǒng)支持多未完成請求(Multiple Outstanding Requests)?,F(xiàn)代DDR內(nèi)存控制器可以管理幾十個待處理的請求,通過bank-level parallelism提升帶寬。

效果:Li等人在2011年更新了這項研究[3],基于Intel Core i7-like模型測試SPEC2006:

允許重疊的miss數(shù) SPECINT2006延遲降低 SPECFP2006延遲降低
1個hit under miss ~9% ~12.5%
2個miss under miss ~9% ~12.5%
64個miss under miss ~9% ~12.5%

有趣的是,現(xiàn)代處理器中,單純增加miss under miss的數(shù)量收益有限。因為:

  1. L3緩存已經(jīng)很大(8-32MB),L2 miss rate本身就很低
  2. 亂序執(zhí)行處理器本身就能掩蓋部分延遲
  3. 內(nèi)存帶寬成為瓶頸,同時發(fā)太多請求反而沖突

3. 硬件實現(xiàn):MSHR

無阻塞緩存的核心部件是MSHR(Miss Status Handling Register,缺失狀態(tài)處理寄存器)[4]

3.1 MSHR是干嘛的

當(dāng)緩存miss時,MSHR記錄:

  • 缺失的內(nèi)存地址
  • 請求類型(load/store)
  • 目標(biāo)寄存器(load的話)
  • 等待該數(shù)據(jù)的后續(xù)指令列表

一個MSHR條目對應(yīng)一個正在處理的miss。條目數(shù)決定了能同時處理的miss數(shù)量。

3.2 實際芯片的MSHR配置

處理器 L1D MSHR L2 MSHR 備注
DEC Alpha 21164[5] 6 entries (MAF) 2 entries (BAF) 1995年經(jīng)典設(shè)計
Intel Core i7[3] 10+ entries 16+ entries 支持復(fù)雜亂序執(zhí)行
NVIDIA GPU[6] 16 entries 128 entries 高并行需求
ARM Cortex-A77 有限支持 有限支持 移動端簡化設(shè)計

Alpha 21164的MSHR叫MAF(Miss Address File),6個條目。這6個條目不僅記錄miss,還合并對同一塊緩存行的多次訪問。比如:

// 假設(shè)addr1和addr2在同一緩存行(64字節(jié)對齊)
load r1, [addr1]  // miss,分配MAF entry 0
load r2, [addr2]  // 同一塊,合并到entry 0,不新增請求

這樣內(nèi)存控制器只發(fā)一次請求,但兩個load都能得到滿足。

3.3 MSHR的硬件結(jié)構(gòu)

簡化版MSHR條目結(jié)構(gòu):

// MSHR Entry 簡化結(jié)構(gòu)
module mshr_entry (
    input valid,           // 該條目是否有效
    input [31:0] miss_addr, // 缺失的物理地址
    input [3:0] block_offset, // 塊內(nèi)偏移(用于merge檢查)
    input is_load,         // 是load還是store
    input [4:0] dest_reg,  // load的目標(biāo)寄存器
    input [7:0] waiting_mask, // 等待該數(shù)據(jù)的指令位圖
    output filled          // 數(shù)據(jù)是否已從內(nèi)存返回
);

// 同一塊檢查邏輯
wire same_block = (addr[31:6] == miss_addr[31:6]);
wire can_merge = valid & same_block & ~filled;

endmodule

MSHR需要支持:

  1. 分配:新miss時找空閑條目
  2. 合并:檢查新請求是否匹配已有條目
  3. 喚醒:數(shù)據(jù)返回時通知所有等待者
  4. 釋放:數(shù)據(jù)填入緩存后回收條目

4. 經(jīng)典案例:DEC Alpha 21164

DEC Alpha 21164是1995年發(fā)布的處理器,最早實現(xiàn)完整無阻塞緩存的商用芯片之一[5][7]。

4.1 緩存層次

層級 大小 相聯(lián)度 延遲 特性
L1I 8KB 直接映射 1 cycle 指令緩存
L1D 8KB 直接映射 2 cycles 雙端口,無阻塞
L2 96KB 3-way 8 cycles 片上,write-back
L3 可選 直接映射 12+ cycles 片外

4.2 無阻塞機(jī)制

21164的L1D支持:

  • 6-entry MAF:位于L1和L2之間,緩存L1 miss的地址
  • 2-entry BAF:位于L2和外部內(nèi)存之間,管理L2 miss
  • Load合并:最多21個load可以合并到同一個MAF entry
  • 雙端口:每周期可以服務(wù)2個load hit,即使正在處理miss

關(guān)鍵設(shè)計:21164的L1D是write-through的,所有store直接下推到L2。這樣L1只需要處理load的miss,簡化了MSHR設(shè)計。

4.3 性能數(shù)據(jù)

21164在300MHz時達(dá)到:

  • SPECint92:約345分
  • SPECfp92:約505分

作為對比,同期Intel Pentium(66MHz)大約只有200分。無阻塞緩存是21164高性能的關(guān)鍵因素之一。


5. 現(xiàn)代處理器的演進(jìn)

5.1 Intel Core系列

現(xiàn)代Intel Core處理器(i3/i5/i7/i9)繼承了無阻塞緩存設(shè)計,但更加復(fù)雜:

  • L1D:32KB,8-way,4-cycle延遲,支持hit under miss
  • L2:256-512KB,支持miss under miss
  • L3:8-32MB,共享,支持大量并發(fā)miss

Intel的MSHR設(shè)計不公開具體條目數(shù),但從性能反推,L1D大約支持10-16個未完成請求,L2支持更多。

5.2 移動端 vs 桌面端差異

特性 桌面/服務(wù)器(Core i7) 移動端(ARM A77)
L1D MSHR 多條目(10+) 有限或沒有
L2 MSHR 支持 有限支持
設(shè)計重點 吞吐量最大化 功耗/面積優(yōu)化
亂序執(zhí)行 深度(192+ entries ROB) 中等(128 entries)

ARM Cortex-A77的L1D實際上是有阻塞的,或者說只支持非常有限的非阻塞能力。因為移動端:

  1. 功耗敏感,MSHR消耗靜態(tài)功耗
  2. 內(nèi)存帶寬有限,同時發(fā)多個請求收益小
  3. 工作負(fù)載不同,移動應(yīng)用緩存miss模式更簡單

6. 什么時候無阻塞緩存沒用

不是所有場景都能從無阻塞緩存受益。

6.1 順序執(zhí)行處理器

如果處理器是順序執(zhí)行的(如簡單的嵌入式MCU),一條指令不完成,后面的指令不能發(fā)射。這時候無阻塞緩存幫不上忙,因為后面的load根本進(jìn)不來。

6.2 內(nèi)存帶寬瓶頸

如果內(nèi)存控制器已經(jīng)飽和,同時發(fā)更多請求只會增加排隊延遲,不會提升吞吐量。這時候需要更大緩存或更快內(nèi)存,而不是更深的MSHR。

6.3 單線程順序訪問

// 指針追逐,每次訪問依賴前一次結(jié)果
while (node) {
    node = node->next;  // 必須等這次load完成才能知道下一次地址
}

這種代碼無法利用hit under miss,因為下一次訪問地址依賴于當(dāng)前l(fā)oad的結(jié)果。亂序執(zhí)行也幫不上忙。


7. 總結(jié)

無阻塞緩存通過MSHR結(jié)構(gòu),讓CPU在等待慢速內(nèi)存時也能處理其他請求。關(guān)鍵要點:

技術(shù) 效果 硬件代價
Hit Under Miss 降低20-30%有效miss penalty MSHR條目,合并邏輯
Miss Under Miss 重疊多個內(nèi)存延遲 更多MSHR條目,內(nèi)存控制器支持

設(shè)計權(quán)衡

  • 高性能處理器(服務(wù)器/桌面):深MSHR,支持大量并發(fā)miss
  • 低功耗處理器(移動/嵌入式):簡化或省略MSHR,節(jié)省面積功耗

歷史意義:從1994年Farkas & Jouppi的理論研究,到1995年Alpha 21164的首次商用實現(xiàn),再到現(xiàn)代Intel/AMD/ARM處理器的標(biāo)配,無阻塞緩存已成為高性能CPU的基石技術(shù)。


參考



  1. Farkas, K. I., & Jouppi, N. P. (1994). Complexity/performance tradeoffs with non-blocking loads. ACM SIGARCH Computer Architecture News, 22(2), 211-222. ?

  2. 計算機(jī)體系結(jié)構(gòu):量化研究方法(第5版),第2章:內(nèi)存層次設(shè)計優(yōu)化。 ?

  3. Li, S., Chen, K., Brockman, J. B., & Jouppi, N. P. (2011). Performance impacts of non-blocking caches in out-of-order processors. HP Labs Technical Report HPL-2011-65. ? ?

  4. Kroft, D. (1981). Lockup-free instruction fetch/prefetch cache organization. ISCA 1981. ?

  5. DEC Alpha 21164 Microprocessor Hardware Reference Manual, EC-QAEQBTE, Digital Equipment Corporation, 1994. ? ?

  6. LATPC: Accelerating GPU Address Translation Using Locality-Aware TLB Prefetching and MSHR Compression. MICRO 2024. ?

  7. Edmondson, J. H., et al. (1995). Superscalar instruction execution in the 21164 Alpha microprocessor. IEEE Micro. ?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容