CPU缓存:L1、L2 和 L3 缓存之间的区别

每个现代处理器都具有少量高速缓存。在过去的几十年中,缓存架构变得越来越复杂:CPU 缓存的级别增加到三级:L1、L2 和 L3,每个块的大小都在增长,缓存关联性也发生了几次变化。但在我们深入研究细节之前,必须知道缓存究竟是什么以及它为什么重要?此外,现代处理器由 L1、L2 和 L3 缓存组成。这些缓存级别之间有什么区别?

高速缓存与系统内存:SRAM 与 DRAM

缓存内存基于速度更快(且价格昂贵)的静态 RAM,而系统内存则利用速度较慢的 DRAM(动态 RAM)。两者的主要区别在于前者采用CMOS技术和晶体管(每块6个),后者采用电容和晶体管。

DRAM 需要不断刷新(由于电容漏电)以更长时间地保留数据。因此,它消耗的功率要大得多,而且速度也更慢,SRAM 无需刷新,效率更高。然而,较高的价格将其使用限制在处理器缓存上。

高速缓存在处理器中的重要性?

CPU缓存:L1、L2 和 L3 缓存之间的区别

现代处理器比 80 年代和 90 年代初的领先了数年。如今,高端消费类芯片的运行频率远远超过 4GHz,而大多数 DDR4 内存模块的额定频率低于 3200MHz。结果,系统内存太慢而无法直接使用 CPU, 为了不严重减慢它们的速度引入了缓存内存。它充当两者之间的中介,存储小块重复使用的数据,或者在某些情况下,存储这些文件的内存地址。

L1、L2 和 L3 缓存:有什么区别?

CPU缓存:L1、L2 和 L3 缓存之间的区别

在现代处理器中,高速缓存分为三个部分:L1、L2 和 L3 高速缓存,按大小和速度递减的顺序排列。L3 缓存是最大也是最慢的(第三代 Ryzen CPU 具有高达 64MB 的大型 L3 缓存)缓存级别。L2 和 L1 比 L3 小得多,速度也快得多,并且每个核心都是分开的。较旧的处理器不包含三级 L3 缓存,系统内存直接与 L2 缓存交互:

CPU缓存:L1、L2 和 L3 缓存之间的区别

L1缓存进一步分为两部分:L1数据缓存和L1指令缓存。后者包含CPU 内核使用的指令,而前者用于保存将被写回主存储器的数据。

L1 缓存不仅用作指令缓存,而且还保存预解码数据和分支信息。此外,虽然 L1 数据缓存通常充当输出缓存,但 L1 指令缓存的行为类似于输入缓存。这在循环参与时很有帮助,因为所需的指令就在提取单元旁边。

CPU缓存:L1、L2 和 L3 缓存之间的区别

现代 CPU 包括用于旗舰处理器的高达 512KB 的 L1 缓存(每个内核 64KB),而服务器部件的功能几乎是后者的两倍。

L2 缓存比 L1 大得多,但同时也更慢。它们在旗舰 CPU 上为 4-8MB(每核 512KB)。每个内核都有自己的 L1 和 L2 缓存,而最后一级,L3 缓存在一个芯片上的所有内核之间共享。

L3 缓存是最低级别的缓存。它从 10MB 到 64MB 不等。服务器芯片具有多达 256MB 的 L3 缓存。此外,与竞争对手的英特尔芯片相比,AMD 的 Ryzen CPU 具有更大的缓存大小。这是因为英特尔方面的 MCM 设计与 Monolithic。

CPU缓存:L1、L2 和 L3 缓存之间的区别

CPU缓存:L1、L2 和 L3 缓存之间的区别

当 CPU 需要数据时,它首先搜索相关内核的 L1 缓存。如果未找到,则接下来搜索 L2 和 L3 缓存。如果找到必要的数据,则称为缓存命中。如果数据不在缓存中,CPU 必须请求将其从主内存或存储加载到缓存中,这需要时间并且会对性能产生不利影响,这称为缓存未命中

一般来说,增加缓存大小会提高缓存命中率,在游戏和其他对延迟敏感的工作负载的情况下更明显。

包含与独占缓存

缓存配置有两种类型:包含缓存和独占缓存。如果存在于高级缓存 (L1) 中的所有数据块都存在于低级缓存 (L2) 中,则低级缓存被称为包含高级缓存。

另一方面,如果较低级别的缓存仅包含较高级别缓存中不存在的数据块,则称该缓存不包含较高级别的缓存。

包含缓存

一个具有两级高速缓存的 CPU。现在,假设请求了一个块 X。如果在 L1 缓存中找到该块,则从 L1 缓存中读取数据并由 CPU 内核消耗。但是,如果该块未在 L1 缓存中找到,但存在于 L2 中,则将从 L2 缓存中提取并放置在 L1 中。

如果 L1 缓存也已满,则从 L1 逐出一个块,为新块腾出空间,而 L2 缓存不变。然而,如果数据块在 L1 和 L2 中都没有找到,那么它就会从内存中取出并放置在两个缓存级别中。在这种情况下,如果 L2 缓存已满并且一个块被逐出为新数据腾出空间,L2 缓存会向 L1 缓存发送无效请求,因此被逐出的块也将从那里删除。由于此失效过程,包含缓存比非包含或独占缓存稍慢。

非包含或独占缓存

现在,让我们考虑具有非包含或独占缓存的相同示例。假设 CPU 内核发送对块 X 的请求。如果在 L1 中找到块 X,则内核从该位置读取并使用它。但是,如果块 X 在 L1 中没有找到,但在 L2 中存在,那么它会从 L2 移动到 L1。如果 L1 中没有空间,则从 L1 中驱逐一个块并存储在 L2 中。这是 L2 缓存填充的唯一方式,因为它充当受害者缓存。如果在 L1 或 L2 中未找到块 X,则将其从内存中取出并放置在 L1 中。

非包容非专属(九)

还有第三个不太常用的缓存策略,称为non-inclusive non-exclusive (NINE)。这里的块既不包含也不排除更高级别的缓存。让我们考虑上一次相同的例子。有一个对块 X 的请求,它在 L1 中找到。然后 CPU 内核将从 L1 缓存中读取并消耗该块。如果在 L1 中找不到该块但在 L2 中存在,则将其从 L2 提取到 L1。L2 缓存保持不变,类似于包含缓存的工作方式。

但是,如果在任一缓存级别中都未找到该块,则会从主内存中提取该块并将其放置在 L1 和 L2 中。但是,如果这导致从 L2 逐出一个块,与包含缓存不同,则 L1 缓存不会失效以从那里清除相同的块。

内存映射概览

抛开关于缓存的基本解释,我们来谈谈系统内存如何与缓存内存对话。这称为缓存或内存映射。高速缓冲存储器被分成块或组。这些块依次被分成 n 个 64 字节的行。系统内存被划分为与缓存相同数量的块(集),然后将两者链接起来。

CPU缓存:L1、L2 和 L3 缓存之间的区别

如果有 1GB 的系统 RAM,那么缓存将被分成 8,192 行,然后分成块。这称为n 路关联缓存。对于 2 路关联高速缓存,每个块包含 2 行,4 路包括 4 行,8 路为 8 行,16 路为 16 行。如果总 RAM 大小为 1GB,则内存中的每个块的大小为 512 KB。

CPU缓存:L1、L2 和 L3 缓存之间的区别

如果有 512 KB 的 4 路关联缓存,则 RAM 将分为 2,048 个块(1GB 为 8192/4)并链接到相同数量的 4 行缓存块。

与 16 路关联缓存的方式相同,缓存分为 512 个块,链接到内存中的 512 (2048 KB) 块,每个缓存块包含 16 行。当缓存用完数据块时,缓存控制器重新加载一组具有所需数据的新块,以继续处理器执行。

CPU缓存:L1、L2 和 L3 缓存之间的区别

N路关联缓存是最常用的映射方法。还有两种称为直接映射和完全关联映射的方法。在前者中,缓存行和内存之间存在硬链接,而在后者的情况下,缓存可以包含任何内存地址。基本上,每一行都可以访问任何主内存块。这种方法的命中率最高。然而,它的实施成本很高,因此芯片制造商大多避免这样做。

CPU缓存:L1、L2 和 L3 缓存之间的区别

完全关联的映射

哪种映射最好?

直接映射是最容易实现的配置,但同时也是效率最低的。例如,如果 CPU 请求给定的内存地址(在这种情况下为 1,000),控制器将从内存中加载 64 字节的行并将其存储在缓存中(1,000 到 1,063)。将来,如果 CPU 需要来自相同地址或紧随其后的地址(1,000 到 1,063)的数据,它们将已经在缓存中。

CPU缓存:L1、L2 和 L3 缓存之间的区别

当 CPU 需要映射到同一高速缓存行的内存块中的两个地址一个接一个时,这就会成为一个问题。例如,如果 CPU 首先请求地址 1,000,然后请求地址 2,000,则会发生缓存未命中,因为这两个地址位于同一个内存块内(块大小为 128 KB)。另一方面,映射到它的缓存行是从地址 1,000 到 1,063 的一行。因此,缓存控制器将在第一个缓存行中加载从地址 2,000 到 2,063 的行,逐出旧数据。这就是为什么直接映射缓存是效率最低的缓存映射技术并在很大程度上被放弃的原因。

CPU缓存:L1、L2 和 L3 缓存之间的区别

全关联映射在某种程度上与直接映射相反。内存缓存的行和 RAM 内存位置之间没有硬链接。缓存控制器可以存储任何地址。上面的问题不会发生。这种缓存映射技术效率最高,命中率最高。然而,正如已经解释过的,它是最难实施。

CPU缓存:L1、L2 和 L3 缓存之间的区别

因此,使用了集关联映射,它是完全关联映射和直接映射之间的混合体。在这里,每个内存块都链接到一组行(取决于 SA 映射的类型),并且每行都可以保存来自映射内存块中任何地址的数据。在 4 路组关联高速缓存中,内存高速缓存上的每个组最多可容纳来自同一内存块的四行。使用 16 路配置,该数字增长到 16。

当映射集上的插槽全部用完时,控制器驱逐其中一个插槽的内容并从同一映射内存块加载不同的数据集。增加组关联内存高速缓存的路数,例如,从 4 路增加到 8 路,每个组有更多可用的高速缓存插槽。但是,如果不增加缓存量,则每个链接内存块的内存大小都会增加。基本上,在不增加整体缓存大小的情况下增加 set cache set 上的可用插槽数量意味着 set 将链接到更大的内存块,由于刷新数量的增加而有效降低了效率。

另一方面,增加缓存大小意味着每个集合中有更多行(假设集合大小也增加)。这意味着每个内存块有更多的链接缓存行。一般来说,这会增加命中率,但它可以提高整体数字的程度是有限的。

上一篇:mybatis(1) SqlSessionTemplate是如何保证的MyBatis中的SqlSession的线程安全的?


下一篇:JDK 1.8特性 Stream是串行还是并行