英特尔酷睿i7处理器使用哪种缓存映射技术?

19

我已经学习了不同的高速缓存映射技术,如直接映射和完全相联或集合相联映射,并了解它们之间的权衡取舍。 (维基百科)

但我很好奇Intel Core i7或AMD处理器现在使用哪种技术?

这些技术是如何发展的?还有需要改进的地方是什么?


1
@Karizma - 不要使用代码格式来强调不是代码的单词或短语。行内代码跨度不应该用于强调,对吧? - Peter Cordes
1个回答

44
直接映射缓存在现代高性能CPU中基本上从不使用。虽然它可以节省功耗,但与同样大小的组相联缓存相比,在命中率方面存在巨大优势,并且控制逻辑稍微复杂一些。如今晶体管预算非常庞大。
软件中经常会有至少几个数组彼此之间相隔4k的倍数,这将在直接映射缓存中产生冲突缺失。(如果一个循环需要同时迭代所有数组,则调整代码以减少冲突缺失可能涉及对它们进行偏斜)
现代CPU速度非常快,DRAM延迟超过200个核心时钟周期,即使对于强大的乱序执行CPU来说,这也很难在缓存缺失时有效地隐藏起来。
多级缓存是必不可少的(并且在所有高性能CPU中都被使用),以提供最低延迟(约4个周期)/高吞吐量,用于最热门的数据(例如每个时钟周期最多2次加载和1次存储),L1D缓存与向量加载/存储执行单元之间的路径为128、256甚至512位),同时仍足够大以缓存一个合理大小的工作集。对于典型工作负载来说,构建一个非常大/非常快/高度关联的缓存,使其性能与当前的多级缓存相当是物理上不可能的;当数据需要物理传输较远时,光速延迟是一个问题。功耗成本也是不可接受的。(事实上,功耗/功率密度是现代CPU的主要限制因素,请参阅《现代微处理器:90分钟指南!》。)

据我所知,除了uop缓存之外,所有x86 CPU的所有级别的缓存都是物理索引/物理标记的。大多数设计中的L1D缓存从页面偏移以下获取其索引位,因此也是VIPT,允许TLB查找与标记提取同时进行,而不会出现任何别名问题。因此,在上下文切换或其他情况下,缓存不需要被清空。(有关多级缓存的更多信息,请参见这个答案以及VIPT速度技巧和一些实际x86 CPU的一些缓存参数。)


私有(每个核心)L1D / L1I和L2缓存是传统的集合关联缓存,通常对于小型/快速缓存为8路或4路。所有现代x86 CPU的缓存行大小为64字节。数据缓存是写回的。(除了AMD Bulldozer系列,在那里L1D是写穿透的,并带有一个小的4kiB写组合缓冲区。) http://www.7-cpu.com/提供了各种微架构的良好缓存组织/延迟数字、带宽以及TLB组织/性能数字,包括许多x86,如Haswell
在英特尔Sandybridge系列中,“L0”解码-uop缓存是组相联的,并且是虚拟寻址的。最多可以缓存来自32字节机器代码块中指令的高达3个块的高达6个uop的解码结果。相关链接:关于涉及Intel SnB系列CPU的微码指令循环分支对齐。(uop缓存对x86来说是一项重大进步:x86指令长度可变且难以快速/并行解码,因此将内部解码结果以及机器代码(L1I$)缓存具有显着的功耗和吞吐量优势。仍然需要强大的解码器,因为uop缓存不大;它在循环中最有效(包括中等到大型循环)。这避免了奔腾4的错误(或基于当时晶体管尺寸的限制),即使用弱解码器并依赖于跟踪缓存。)
现代的Intel(和AMD,我猜)L3,也就是LLC,也就是最后一级缓存使用的索引函数不仅仅是一个地址位的范围。它是一个哈希函数,可以更好地分配事物,以减少固定步长的冲突。根据Intel的说法,我的缓存应该是24路关联的,但实际上只有12路,这是为什么呢?
自 Nehalem 开始,Intel 使用了一个大型的包容性共享 L3 缓存,它在核心之间过滤一致性流量。即当一个核心读取另一个核心的 L1d 中处于已修改状态的数据时,L3 标签会指明是哪个核心,因此只需向该核心发送 RFO(Read For Ownership)请求,而不是广播给所有核心。现代 Intel CPU 的 L3 缓存是如何组织的? 共享主要是指没有私有的 L2 或 L1 缓存可以拥有缓存行的副本而 L3 不知道。如果某个私有缓存中的行处于独占或已修改状态,L3 将对该行具有无效数据,但标签仍将指明可能拥有该副本的核心。确定不拥有副本的核心无需收到相关消息,从而节省了核心与 L3 之间内部链路上的功耗和带宽。详情请参阅为什么片上缓存一致性会一直存在?,了解 Intel "i7"(即 Nehalem 和 Sandybridge 系列,这些虽然是不同架构,但使用相同的缓存层次结构)中的片上缓存一致性的更多细节。
Core2Duo在最后一级缓存(L2)上有一个共享的缓存,但在L2缺失时生成RFO(Read-For-Ownership)请求的速度较慢。因此,具有适合于L1d的小缓冲区的核心之间的带宽与不适合于L2的大缓冲区(即DRAM速度)一样慢。当缓冲区适合于L2但不适合于L1d时,存在一系列快速大小,因为写入核心将其自己的数据驱逐到L2,其他核心的加载可以命中而不生成RFO请求。(请参见Ulrich Drepper的《每个程序员都应该了解的内存知识》中的图3.27:带有2个线程的Core 2带宽。(完整版本在此处)。
Skylake-AVX512的每个核心的L2缓存更大(1MiB而不是256k),而L3缓存(LLC)每个核心的切片更小。它不再是包容性的。它使用网状网络而不是环形总线将核心连接在一起。请参阅这篇AnandTech文章(但其中一些页面上的微架构细节有一些不准确,请看我留下的评论)。
Intel® Xeon® Processor Scalable Family Technical Overview中得知,由于LLC的非包容性特性,LLC中缺少一个缓存行并不意味着该行不存在于任何核心的私有缓存中。因此,在LLC未分配缓存行时,使用了一种嗅探过滤器来跟踪缓存行在核心的L1或MLC中的位置。在上一代CPU中,共享的LLC本身负责这个任务。
这个"嗅探过滤器"只有在不能产生错误的情况下才有用。向没有某一行副本的核心发送无效化或RFO(MESI)是可以的。但是,当另一个核心请求独占访问某一行时,让一个核心保留该行的副本是不可接受的。因此,它可能是一个标签包容式的追踪器,知道哪些核心可能有哪些行的副本,但不缓存任何数据。
或者,即使不严格包括所有的L2 / L1标签,嗅探过滤器可能仍然有用。我对多核/多插槽嗅探协议不是专家。我认为相同的嗅探过滤器也可以帮助过滤插槽之间的嗅探请求。(在Broadwell和更早的版本中,只有四插槽及更高版本的Xeon才具有用于内核间流量的嗅探过滤器;仅双插槽的Broadwell Xeon和更早版本不会过滤两个插槽之间的嗅探请求。)
AMD Ryzen 使用独立的L3缓存来为核心集群提供支持,因此在多个核心之间共享的数据必须在每个集群的L3中进行复制。此外,一个集群中的核心对另一个集群中的核心可见所需的时间更长,一致性请求必须通过集群之间的互连进行传输。(类似于多插槽Intel系统中的插槽之间,每个CPU套件都有自己的L3。)
因此,这给我们带来了NUCA(非均匀缓存访问),类似于通常在多插槽系统中获得的NUMA(非均匀内存访问),其中每个处理器都有内置的内存控制器,并且访问本地内存比访问连接到另一个插槽的内存更快。
最近的英特尔多插槽系统具有可配置的嗅探模式,理论上您可以调整NUMA机制以使其最适合您正在运行的工作负载。请参阅Intel关于Broadwell-Xeon的页面,了解可用嗅探模式的表格和描述。
另一个进步/演变是在IvyBridge及以后的处理器上采用了自适应替换策略(L3缓存)。这可以减少当某些数据具有时间局部性,但工作集的其他部分要大得多时所产生的污染。(例如,使用伪LRU(L1和L2缓存使用)循环遍历一个巨大的数组将会驱逐所有内容,只留下L3缓存中来自该数组的数据,而这些数据不久后就不会再被访问。自适应替换试图缓解这个问题。)显然,至少在L1和L2缓存中,英特尔现在使用某种形式的LFU替换。(待办事项:找到更权威和详细的信息。)
进一步阅读:

1
从安全角度来看,使用经典的索引和替换可能被视为有问题的。替换策略可以进一步优化,压缩可以被利用,通过减少容量使用实现节能,接近使用(NUCA和生产者到消费者的数据推送),一致性开销,共享管理(例如资源竞标和隔离)。低垂果实可能已经被很好地收获,但似乎仍然有相当数量的果实剩余。 - user2467198
1
@HadiBrais:没错,自 Nehalem 以来,英特尔使用 L3 来支持一致性流量。而我关于 Core 2 的看法是错误的:它只是在处理 L2 缺失时的 RFOs 速度较慢,但另一个核心可以在 L2 中命中脏数据。Ulrich Drepper 的内存论文中有一些 Core2 基准测试,显示在缓冲区适合 L1d 时,两个核之间的复制速度达到 DRAM 速度,但并未声称实际通过 DRAM 进行。当一个核心的写入强制将数据驱逐到 L2 中,然后另一个核心读取时,速度会快得多。https://lwn.net/Articles/252125/ 这几乎肯定是我(错误地)记住的内容。 - Peter Cordes
1
@HadiBrais:更新了这个答案。感谢指出我的说法是虚假的;你完全正确,支持一致性数据并不需要包容性。 - Peter Cordes
1
这里也得到了确认(https://software.intel.com/en-us/articles/intel-xeon-processor-scalable-family-technical-overview)- “由于LLC的非包容性,LLC中缺少缓存行并不表示该行不存在于任何核心的私有缓存中。因此,在LLC未分配时,使用嗅探过滤器来跟踪缓存行在核心的L1或MLC中的位置。在上一代CPU上,共享的LLC本身负责这个任务。” - Leeor
1
骑士着陆芯片在缓存模式下使用直接映射缓存。 - Jacek Tomaka
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接