无阻塞缓存:让CPU在等内存时也不闲着

缓存miss了咋整?传统做法是CPU干等着,直到数据从内存回来。无阻塞缓存(Non-blocking Cache)打破了这个规矩——即使前面有个miss正在处理,后面的请求该干嘛干嘛。这篇聊聊这个技术的原理、实现和效果。


1. 阻塞缓存的痛点

想象你在餐厅排队点餐:

  • 前面的人点了个复杂的套餐(缓存miss,需要等很久)
  • 你只想点杯咖啡(缓存hit,很快)
  • 但阻塞式服务要求你必须等前面的人拿完餐,才能点你的咖啡

这显然不合理。CPU里的缓存也是这个道理。

1.1 实际性能损失

1994年,Farkas和Jouppi在DEC Western Research Lab做了个实验[1]。他们模拟了一个8KB单级缓存,miss penalty 14个周期(90年代初的典型配置)。

结果发现:SPECINT92基准测试中,处理器因为缓存miss停顿的时间占总执行时间的比例高达20-30%。这意味着每5条指令就有1条在等内存。


2. 无阻塞缓存的两级优化

无阻塞缓存不是单一技术,而是两个层次的优化:

2.1 Hit Under Miss(缺失时命中)

核心思想:前面有个load miss了,后面的load如果hit,照样可以服务。

效果:Farkas & Jouppi的测试显示[2],允许1个hit under miss时:

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

FP程序提升更明显,因为科学计算常有规律的内存访问模式,miss后紧接着的访问往往还在缓存里。

2.2 Miss Under Miss(缺失时缺失)

核心思想:允许同时发出多个内存请求,重叠它们的延迟。

这需要内存系统支持多未完成请求(Multiple Outstanding Requests)。现代DDR内存控制器可以管理几十个待处理的请求,通过bank-level parallelism提升带宽。

效果:Li等人在2011年更新了这项研究[3],基于Intel Core i7-like模型测试SPEC2006:

允许重叠的miss数 SPECINT2006延迟降低 SPECFP2006延迟降低
1个hit under miss ~9% ~12.5%
2个miss under miss ~9% ~12.5%
64个miss under miss ~9% ~12.5%

有趣的是,现代处理器中,单纯增加miss under miss的数量收益有限。因为:

  1. L3缓存已经很大(8-32MB),L2 miss rate本身就很低
  2. 乱序执行处理器本身就能掩盖部分延迟
  3. 内存带宽成为瓶颈,同时发太多请求反而冲突

3. 硬件实现:MSHR

无阻塞缓存的核心部件是MSHR(Miss Status Handling Register,缺失状态处理寄存器)[4]

3.1 MSHR是干嘛的

当缓存miss时,MSHR记录:

  • 缺失的内存地址
  • 请求类型(load/store)
  • 目标寄存器(load的话)
  • 等待该数据的后续指令列表

一个MSHR条目对应一个正在处理的miss。条目数决定了能同时处理的miss数量。

3.2 实际芯片的MSHR配置

处理器 L1D MSHR L2 MSHR 备注
DEC Alpha 21164[5] 6 entries (MAF) 2 entries (BAF) 1995年经典设计
Intel Core i7[3] 10+ entries 16+ entries 支持复杂乱序执行
NVIDIA GPU[6] 16 entries 128 entries 高并行需求
ARM Cortex-A77 有限支持 有限支持 移动端简化设计

Alpha 21164的MSHR叫MAF(Miss Address File),6个条目。这6个条目不仅记录miss,还合并对同一块缓存行的多次访问。比如:

// 假设addr1和addr2在同一缓存行(64字节对齐)
load r1, [addr1]  // miss,分配MAF entry 0
load r2, [addr2]  // 同一块,合并到entry 0,不新增请求

这样内存控制器只发一次请求,但两个load都能得到满足。

3.3 MSHR的硬件结构

简化版MSHR条目结构:

// MSHR Entry 简化结构
module mshr_entry (
    input valid,           // 该条目是否有效
    input [31:0] miss_addr, // 缺失的物理地址
    input [3:0] block_offset, // 块内偏移(用于merge检查)
    input is_load,         // 是load还是store
    input [4:0] dest_reg,  // load的目标寄存器
    input [7:0] waiting_mask, // 等待该数据的指令位图
    output filled          // 数据是否已从内存返回
);

// 同一块检查逻辑
wire same_block = (addr[31:6] == miss_addr[31:6]);
wire can_merge = valid & same_block & ~filled;

endmodule

MSHR需要支持:

  1. 分配:新miss时找空闲条目
  2. 合并:检查新请求是否匹配已有条目
  3. 唤醒:数据返回时通知所有等待者
  4. 释放:数据填入缓存后回收条目

4. 经典案例:DEC Alpha 21164

DEC Alpha 21164是1995年发布的处理器,最早实现完整无阻塞缓存的商用芯片之一[5][7]

4.1 缓存层次

层级 大小 相联度 延迟 特性
L1I 8KB 直接映射 1 cycle 指令缓存
L1D 8KB 直接映射 2 cycles 双端口,无阻塞
L2 96KB 3-way 8 cycles 片上,write-back
L3 可选 直接映射 12+ cycles 片外

4.2 无阻塞机制

21164的L1D支持:

  • 6-entry MAF:位于L1和L2之间,缓存L1 miss的地址
  • 2-entry BAF:位于L2和外部内存之间,管理L2 miss
  • Load合并:最多21个load可以合并到同一个MAF entry
  • 双端口:每周期可以服务2个load hit,即使正在处理miss

关键设计:21164的L1D是write-through的,所有store直接下推到L2。这样L1只需要处理load的miss,简化了MSHR设计。

4.3 性能数据

21164在300MHz时达到:

  • SPECint92:约345分
  • SPECfp92:约505分

作为对比,同期Intel Pentium(66MHz)大约只有200分。无阻塞缓存是21164高性能的关键因素之一。


5. 现代处理器的演进

5.1 Intel Core系列

现代Intel Core处理器(i3/i5/i7/i9)继承了无阻塞缓存设计,但更加复杂:

  • L1D:32KB,8-way,4-cycle延迟,支持hit under miss
  • L2:256-512KB,支持miss under miss
  • L3:8-32MB,共享,支持大量并发miss

Intel的MSHR设计不公开具体条目数,但从性能反推,L1D大约支持10-16个未完成请求,L2支持更多。

5.2 移动端 vs 桌面端差异

特性 桌面/服务器(Core i7) 移动端(ARM A77)
L1D MSHR 多条目(10+) 有限或没有
L2 MSHR 支持 有限支持
设计重点 吞吐量最大化 功耗/面积优化
乱序执行 深度(192+ entries ROB) 中等(128 entries)

ARM Cortex-A77的L1D实际上是有阻塞的,或者说只支持非常有限的非阻塞能力。因为移动端:

  1. 功耗敏感,MSHR消耗静态功耗
  2. 内存带宽有限,同时发多个请求收益小
  3. 工作负载不同,移动应用缓存miss模式更简单

6. 什么时候无阻塞缓存没用

不是所有场景都能从无阻塞缓存受益。

6.1 顺序执行处理器

如果处理器是顺序执行的(如简单的嵌入式MCU),一条指令不完成,后面的指令不能发射。这时候无阻塞缓存帮不上忙,因为后面的load根本进不来。

6.2 内存带宽瓶颈

如果内存控制器已经饱和,同时发更多请求只会增加排队延迟,不会提升吞吐量。这时候需要更大缓存或更快内存,而不是更深的MSHR。

6.3 单线程顺序访问

// 指针追逐,每次访问依赖前一次结果
while (node) {
    node = node->next;  // 必须等这次load完成才能知道下一次地址
}

这种代码无法利用hit under miss,因为下一次访问地址依赖于当前load的结果。乱序执行也帮不上忙。


7. 总结

无阻塞缓存通过MSHR结构,让CPU在等待慢速内存时也能处理其他请求。关键要点:

技术 效果 硬件代价
Hit Under Miss 降低20-30%有效miss penalty MSHR条目,合并逻辑
Miss Under Miss 重叠多个内存延迟 更多MSHR条目,内存控制器支持

设计权衡

  • 高性能处理器(服务器/桌面):深MSHR,支持大量并发miss
  • 低功耗处理器(移动/嵌入式):简化或省略MSHR,节省面积功耗

历史意义:从1994年Farkas & Jouppi的理论研究,到1995年Alpha 21164的首次商用实现,再到现代Intel/AMD/ARM处理器的标配,无阻塞缓存已成为高性能CPU的基石技术。


参考



  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. 计算机体系结构:量化研究方法(第5版),第2章:内存层次设计优化。

  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.

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容