caching - L1缓存通常是分体式设计,而L2、L3缓存却是统一设计,为什么呢?

标签 caching cpu-architecture cpu-cache micro-architecture

我在 this 中阅读了缓存的拆分设计与统一设计的优缺点线程。

根据我的理解,拆分设计的主要优点是:拆分设计使我们能够将指令缓存放置在靠近指令获取单元的位置,将数据缓存放置在靠近内存的位置单元,从而同时减少两者的延迟。主要缺点是:指令和数据缓存的组合空间可能无法得到有效利用。仿真表明,相同总大小的统一缓存具有更高的命中率。

但是,我无法找到“为什么(至少在大多数现代处理器中)L1 缓存遵循分离设计,而 L2/L3 缓存遵循统一设计”这个问题的直观答案。

最佳答案

分割 L1 的大部分原因是为了在两个缓存之间分配必要的读/写端口(以及带宽),并将它们物理地放置在靠近数据加载/存储与管道的指令获取部分的位置。

L1d 还可以处理字节加载/存储(在某些 ISA 上,未对齐的更宽加载/存储)。在想要 handle that with maximum efficiency 的 x86 CPU 上(不是包含字的 RMW),Intel 的 L1d 只能使用奇偶校验,而不使用 ECC。 L1i 只需要处理固定宽度的提取,通常是一些简单的东西,比如对齐的 16 字节 block ,并且它总是“干净”,因为它是只读的,所以它只需要检测错误(不正确) ),然后重新获取。因此,每行数据的开销较小,例如每 8 或 16 字节只需几个奇偶校验位。

参见Why is the size of L1 cache smaller than that of the L2 cache in most of the processors?回复:不可能构建一个大型统一 L1 缓存,其容量是分离 L1i/d 的两倍、相同的延迟和带宽总和。(由于功耗至少高得令人望而却步)读/写端口的大小和数量,但由于物理距离的原因,实际上可能不可能出现延迟。)

这些因素对于 L2 都不重要(或者在未对齐/字节存储的情况下根本不存在)。可用于代码或数据的总容量在那里最有用,根据需求竞争性共享。

任何工作负载在同一时钟周期内出现大量 L1i L1d 缺失的情况都是非常罕见的,因为频繁的代码缺失意味着前端停滞,后端将耗尽要执行的加载/存储指令。 (频繁的 L1i 缺失很少见,但频繁的 L1d 缺失在某些正常工作负载中确实会发生,例如循环遍历不适合 L1d 的数组、大型哈希表或其他更分散的访问模式。)无论如何,这意味着数据可以正常情况下可以获得大部分L2总带宽预算,统一的L2仍然只需要1个读端口。

您链接的@Hadi 的答案确实涵盖了大部分原因,但我想写一个简化/摘要的答案并没有什么坏处。

关于caching - L1缓存通常是分体式设计,而L2、L3缓存却是统一设计,为什么呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64184265/

相关文章:

c - 使用 Cache-Line 对齐对 C 中全局共享状态的修改进行无锁检查

compiler-construction - 如何为这段代码创建无分支代码?

performance - 访问映射到同一物理地址的虚拟地址是否会受到惩罚?

amazon-ec2 - 虚拟化环境中的 CPU 亲和性

asp.net - 在 ASP.NET 中缓存所有用户

cpu-architecture - 两个进程可以在一个 CPU 内核上同时运行吗?

arm - 优化不同阵列的 ARM 缓存使用

python - 如何强制 Django 忽略任何缓存并重新加载数据?

node.js - 使用 NGINX + Express 进行 URL 指纹识别/主动缓存

C++:仿函数的缓存友好性