intel core i7 处理器使用哪种缓存映射技术?

2024-03-03

我了解了不同的缓存映射技术,例如直接映射和完全关联或集关联映射,以及这些技术之间的权衡。 (维基百科 https://en.wikipedia.org/wiki/Cache_placement_policies)

但我很好奇现在Intel core i7和AMD处理器用的是哪一种?

这些技术是如何演变的?以及还有哪些需要改进的地方?


现代高性能CPU中基本上不使用直接映射缓存。相同大小的组相联高速缓存在命中率方面的巨大优势超过了节能,而控制逻辑的复杂性仅增加了一点。如今晶体管预算非常大。

软件中至少有几个彼此间隔为 4k 倍数的阵列是很常见的,这会在直接映射缓存中产生冲突未命中。 (如果循环需要一次迭代所有数组,则调整具有多个数组的代码可能会涉及倾斜它们以减少冲突遗漏)

现代 CPU 的速度非常快,以至于 DRAM 延迟超过 200 个核心时钟周期,即使对于功能强大的乱序执行 CPU 来说,这个延迟也太大了,无法很好地隐藏缓存未命中的情况。


多级缓存必不可少(并且使用的是所有高性能CPU)为最热门的数据(例如,每个时钟最多 2 次加载和 1 次存储 https://electronics.stackexchange.com/questions/329789/how-can-cache-be-that-fast/329955#329955,在 L1D 缓存和向量加载/存储执行单元之间具有 128、256 甚至 512 位路径),同时仍然足够大以缓存合理大小的工作集。对于典型工作负载来说,构建一个非常大/非常快/高度关联的缓存,其性能与当前的多级缓存一样,在物理上是不可能的;当数据必须物理传输很远时,光速延迟是一个问题。电力成本也将令人望而却步。 (事实上​​,功率/功率密度是现代 CPU 的主要限制因素,请参见现代微处理器:90 分钟指南! http://www.lighterra.com/papers/modernmicroprocessors/.)

在我所知道的所有 x86 CPU 中,所有级别的缓存(除了 uop 缓存)都有物理索引/物理标记。大多数设计中的 L1D 缓存从页面偏移下方获取索引位,因此也是 VIPT,允许 TLB 查找与标签获取并行发生,但不会出现任何别名问题。因此,不需要在上下文切换或其他任何情况下刷新缓存。 (看有关多级缓存的更多信息,请参阅此答案 https://stackoverflow.com/questions/4666728/why-is-the-size-of-l1-cache-smaller-than-that-of-the-l2-cache-in-most-of-the-pro/38549736#38549736一般情况和 VIPT 速度技巧,以及一些实际 x86 CPU 的一些缓存参数。)


私有(每核)L1D / L1I 和 L2 缓存是传统的组关联缓存,通常是 8 路或 4 路,用于小/快速缓存。所有现代 x86 CPU 上的高速缓存行大小均为 64 字节。数据缓存是回写式的。 (AMD Bulldozer 系列除外,其中 L1D 使用小型 4kiB 写入组合缓冲区进行直写。)

http://www.7-cpu.com/ http://www.7-cpu.com/对于各种微架构(包括许多 x86)具有良好的缓存组织/延迟数、带宽和 TLB 组织/性能数像哈斯韦尔 http://www.7-cpu.com/cpu/Haswell.html.

英特尔 Sandybridge 系列中的“L0”解码 uop 缓存是集关联且虚拟寻址的。最多 3 个块(最多 6 个微指令)可以缓存 32 字节机器代码块中指令的解码结果。有关的:涉及 Intel SnB 系列 CPU 上微编码指令的循环的分支对齐 https://stackoverflow.com/questions/26907523/branch-alignment-for-loops-involving-micro-coded-instructions-on-intel-snb-famil。 (uop 缓存对于 x86 来说是一个巨大的进步:x86 指令是可变长度的并且难以快速/并行解码,因此缓存内部解码结果以及机器代码 (L1I$) 具有显着的功率和吞吐量优势。仍然需要解码器,因为 uop 缓存不大;它在循环(包括中到大循环)中最有效。这避免了 Pentium4 的错误(或基于当时传输器大小的限制),即解码器较弱并依赖于跟踪缓存。)


现代英特尔(和 AMD,我认为)L3 又名 LLC 又名最后一级缓存使用的索引功能不仅仅是地址位范围。它是一个哈希函数,可以更好地分配事物,以减少固定步幅的冲突。根据英特尔的说法,我的缓存应该是 24 路关联,尽管它是 12 路,这是怎么回事? https://stackoverflow.com/questions/37162132/according-to-intel-my-cache-should-be-24-way-associative-though-its-12-way-how#comment82934821_47974587.


从尼黑勒姆开始,英特尔使用了large 包括的共享 L3 缓存,过滤内核之间的一致性流量。即,当一个核心读取另一个核心的 L1d 中处于修改状态的数据时,L3 标签会指示哪个核心,因此 RFO(读取所有权)只能发送到该核心,而不是广播。现代 Intel CPU L3 缓存是如何组织的? https://stackoverflow.com/questions/28891349/how-are-the-modern-intel-cpu-l3-caches-organized。包容性属性很重要,因为这意味着私有 L2 或 L1 缓存不能在 L3 不知道的情况下拥有缓存行的副本。如果它在私有缓存中处于独占或修改状态,L3 将具有该行的无效数据,但标签仍会说明哪个核心可能有副本。绝对没有副本的核心不需要发送有关它的消息,从而节省了核心和 L3 之间的内部链路的功耗和带宽。看为什么片上缓存一致性会继续存在 http://Why%20On-Chip%20Cache%20Coherence%20is%20Here%20to%20Stay有关英特尔“i7”(即 Nehalem 和 Sandybridge 系列,它们是不同的架构,但使用相同的缓存层次结构)中片上缓存一致性的更多详细信息。

Core2Duo具有共享的最后一级缓存 (L2),但在 L2 未命中时生成 RFO(读取所有权)请求的速度很慢。因此,具有适合 L1d 的小缓冲区的内核之间的带宽与不适合 L2 的大缓冲区的内核之间的带宽一样慢(即 DRAM 速度)。当缓冲区适合 L2 但不适合 L1d 时,大小范围很快,因为写入核心将自己的数据逐出到 L2,而其他核心的负载可以在不生成 RFO 请求的情况下命中。 (看图 3.27:2 个线程的核心 2 带宽 http://Memory%20part%202:%20CPU%20caches在 Ulrich Drepper 的《每个程序员都应该了解内存》中。 (完整版在这里 https://stackoverflow.com/questions/8126311/what-every-programmer-should-know-about-memory/47714514#47714514).


Skylake-AVX512 具有更大的每核 L2(1MiB,而不是 256k),以及每核更小的 L3 (LLC) 切片。不再具有包容性。它使用网状网络而不是环形总线将核心相互连接。看这篇 AnandTech 文章 https://www.anandtech.com/show/11550/the-intel-skylakex-review-core-i9-7900x-i7-7820x-and-i7-7800x-tested/4(但其他页面上的微架构细节有一些不准确,看我留下的评论 https://www.anandtech.com/comments/11550/the-intel-skylakex-review-core-i9-7900x-i7-7820x-and-i7-7800x-tested/565778).

From 英特尔® 至强® 处理器可扩展家族技术概述 https://software.intel.com/en-us/articles/intel-xeon-processor-scalable-family-technical-overview

因为有限责任公司的非包容性,LLC 中缺少缓存行并不表示该行不存在于任何内核的私有缓存中。因此,当高速缓存行未在 LLC 中分配时,使用窥探过滤器来跟踪内核的 L1 或 MLC 中的高速缓存行的位置。在上一代 CPU 上,共享 LLC 本身负责此任务。

这种“窥探过滤器”只有在不会出现漏报的情况下才有用。发送无效或 RFO 是可以的(MESI https://en.wikipedia.org/wiki/MESI_protocol)到没有行副本的核心。当另一个核心请求独占访问某行时,让一个核心保留该行的副本是不行的。因此,它可能是一个包含标签的跟踪器,它知道哪些核心可能拥有哪一行的副本,但不缓存任何数据。

或者也许窥探过滤器在不严格包含所有 L2 / L1 标签的情况下仍然有用。我不是多核/多插槽监听协议方面的专家。我think相同的监听过滤器还可以帮助过滤套接字之间的监听请求。 (在 Broadwell 及更早版本中,只有四路和更高版本的 Xeon 具有针对核心间流量的窥探过滤器;仅双插槽 Broadwell Xeon 及更早版本不会过滤两个插槽之间的监听请求 https://stackoverflow.com/questions/48872306/what-comes-after-intel-xeon-broadwell-dual-processors.)


AMD 锐龙对核心集群使用单独的 L3 缓存 https://www.anandtech.com/show/11170/the-amd-zen-and-ryzen-7-review-a-deep-dive-on-1800x-1700x-and-1700/9,因此必须在每个集群的 L3 中复制跨多个核心共享的数据。同样重要的是,来自一个集群中的核心的写入需要更长的时间才能对另一集群中的核心可见,并且一致性请求必须通过集群之间的互连。 (类似于多插槽 Intel 系统中的插槽之间,每个 CPU 包都有自己的 L3。)

因此,这为我们提供了 NUCA(非统一缓存访问),类似于多插槽系统中常见的 NUMA(非统一内存访问),其中每个处理器都内置了一个内存控制器,并且访问本地内存是比访问连接到另一个插槽的内存更快。


最新的 Intel 多插槽系统具有可配置的监听模式,因此理论上您可以调整 NUMA 机制,使其最适合您正在运行的工作负载。看Intel 关于 Broadwell-Xeon 的页面 https://software.intel.com/en-us/articles/intel-xeon-processor-e5-2600-v4-product-family-technical-overview获取可用侦听模式的表格和说明。


另一个进步/进化是IvyBridge 及更高版本的 L3 中的自适应替换策略 http://blog.stuffedcow.net/2013/01/ivb-cache-replacement/。当某些数据具有时间局部性但工作集的其他部分要大得多时,这可以减少污染。 (即循环一个巨大的数组伪LRU https://en.wikipedia.org/wiki/Pseudo-LRU(L1 和 L2 缓存使用的)将逐出所有内容,留下 L3 缓存仅缓存数组中不会很快再次触及的数据。自适应替换试图缓解这个问题。)显然 https://stackoverflow.com/questions/76977137/why-number-of-processor-cycles-required-to-process-a-single-array-element-grows?noredirect=1#comment135718763_76977137英特尔使用某种形式LFU 更换 https://en.wikipedia.org/wiki/Least_frequently_used这些天至少在 L1 和 L2 中。 (TODO:找到更多权威和详细的信息。)


进一步阅读:

  • 《每个程序员都应该了解的内存知识》中有多少仍然有效? https://stackoverflow.com/questions/8126311/what-every-programmer-should-know-about-memory/47714514#47714514
  • 为什么 Skylake 在单线程内存吞吐量方面比 Broadwell-E 好很多? https://stackoverflow.com/questions/39260020/why-is-skylake-so-much-better-than-broadwell-e-for-single-threaded-memory-throug? (多核 Xeon CPU 上的单线程内存带宽受 max_concurrency/延迟限制,而不是 DRAM 带宽)。
  • http://users.atw.hu/instlatx64/ http://users.atw.hu/instlatx64/用于内存性能计时结果
  • http://www.7-cpu.com/ http://www.7-cpu.com/用于缓存/TLB 组织和延迟数。
  • http://agner.org/optimize/ http://agner.org/optimize/有关微体系结构详细信息(主要是关于执行管道,而不是内存)和 asm / C++ 优化指南。
  • Stack Overflow 的 x86 标签 wiki https://stackoverflow.com/tags/x86/info有一个性能部分,其中包含指向这些内容以及更多内容的链接。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

intel core i7 处理器使用哪种缓存映射技术? 的相关文章

  • 如何正确确定Intel处理器的-march和-mtune?

    我目前正在从源代码构建一个对我来说性能至关重要的软件 因此 我想对其进行优化 以便在我的特定 Intel CPU 上运行 构建过程要求我设置 march 和 mtune 标志 如果在我的处理器节点上我使用 gcc march native
  • 链接描述文件未按预期跳过字节

    因此 我有这个汇编文件 我使用 GNU as 进行汇编 并使用链接器脚本与 GNU ld 进行链接 链接描述文件 boot ld INPUT boot o OUTPUT boot out ENTRY boot start SECTIONS
  • 早期的BIOS怎么能使用CALL呢?

    我纯粹是出于爱好原因 试图理解 PC 中的一些低级代码 我为随机的旧千兆字节 MB 下载了一个过时的 BIOS ROM 映像 https www gigabyte com Motherboard GA 8I845GE775 G rev 10
  • 如何在汇编程序中使用 C 库?

    我想知道如何用汇编语言编写文本编辑器 但现代操作系统需要 C 库 特别是对于它们的窗口系统 我找到了这个page http pengu1n is programmer com posts 8304 html 这对我有很大帮助 但我想知道是否
  • 获取比较指令的值

    据我了解 cmp 指令将设置标志寄存器中的一些位 然后 您可以使用 jle jnp 等指令基于这些指令进行分支 我想知道如何从比较中恢复整数值 示例 以下是有效的 c 语法 y x a gt 13 因此 a 与 13 进行比较 得到 tru
  • 如何禁用浮点单元(FPU)?

    我想在 x86 系统中禁用 FPU MMX SSE 指令 并且我将为设备不可用异常实现一个处理程序 我已经提到过控制寄存器 wiki 页面 http en wikipedia org wiki Control register 看来我必须在
  • 跨 AVX 通道的最佳方式是什么?

    有些问题具有类似的标题 但我的问题涉及其他地方未涵盖的一个非常具体的用例 我有 4 个 128d 寄存器 x0 x1 x2 x3 我想将它们的内容重新组合在 5 个 256d 寄存器 y0 y1 y2 y3 y4 中 以准备其他计算 on
  • C/C++ 中的简单“Hello World”内联汇编语言程序

    我使用 devcpp 和 borland c 编译器 asm mov ax 4 I O Func mov bx 1 Output func mov cx name address of the string mov dx 6 length
  • 为什么当设置为 TLS 选择器时,ES 和 DS 在 64 位内核上最终会归零?

    下面的 32 位程序调用set thread area 2 http linux die net man 2 set thread area在 GDT 中创建一个条目 该条目旨在用于 TLS 通常将结果选择器放入FS or GS并成功使用
  • 为 Visual Studio 应用程序设置平台目标的目的是什么?

    对于任何 VS 项目 都可以在该项目的构建属性中设置平台目标 您可以将其设置为任何 CPU x86 x64 或 Itanium 我的问题是 如果我将此值设置为 x86 是否意味着我无法在 x64 计算机上运行该项目 如果是这样 为什么还要使
  • 为什么不能执行 mov [eax], [ebx] [重复]

    这个问题在这里已经有答案了 我可以做这个 mov eax ebx 和这个 mov eax ebx 甚至这个 mov eax ebx 但不是这个 错误C2415 mov eax ebx 只是wtf 为什么 它与 ptr1 ptr2 相同 为什
  • NASM 轮班操作员

    您将如何在寄存器上进行 NASM 中的位移位 我读了手册 它似乎只提到了这些操作员 gt gt lt lt 当我尝试使用它们时 NASM 抱怨移位运算符处理标量值 您能解释什么是标量值并举例说明如何使用 gt gt and lt lt 另外
  • 奇怪的 MSC 8.0 错误:“ESP 的值未在函数调用中正确保存...”

    我们最近尝试将一些 Visual Studio 项目分解为库 并且在测试项目中一切似乎都编译和构建得很好 其中一个库项目作为依赖项 然而 尝试运行该应用程序给我们带来了以下令人讨厌的运行时错误消息 运行时检查失败 0 ESP 的值未在函数调
  • 从汇编程序获取命令行参数

    通读 专业汇编语言书籍 似乎它提供了用于读取命令行参数的错误代码 我纠正了一点 现在它从段错误变成了读取参数计数 然后是段错误 这是完整的代码 data output1 asciz There are d params n output2
  • 用于预乘 ARGB 的 SSE alpha 混合

    我正在尝试编写一个支持 SSE 的 alpha 合成器 这就是我想出的 首先 混合两个 4 像素向量的代码 alpha blend two 128 bit 16 byte SSE vectors containing 4 pre multi
  • Nasm 打印到下一行

    我用 nasm Assembly 编写了以下程序 section text global start start Input variables mov edx inLen mov ecx inMsg mov ebx 1 mov eax 4
  • AVX-512CD(冲突检测)与原子变量访问有何不同?

    所以我在看他们展示了如何 void Histogram const float age int const hist const int n const float group width const int m const float o
  • CPU寄存器和多任务处理

    我目前正在学习汇编 我很困惑 CPU 寄存器如何与多任务一起工作 所以在多任务系统中 CPU可以随时暂停某个程序的执行并运行另一个程序 那么在这一步中寄存器值是如何保存的呢 寄存器是压入堆栈还是以其他方式 CPU 寄存器如何与多任务一起工作
  • X86 预取优化:“计算 goto”线程代码

    我有一个相当重要的问题 我的计算图有循环和多个 计算路径 我没有制作一个调度程序循环 其中每个顶点将被一一调用 而是将所有预先分配的 框架对象 放置在堆中 代码 数据 这有点类似于线程代码 甚至更好 CPS 只是在堆中跳转 执行代码 每个代
  • 为什么 FMA _mm256_fmadd_pd() 内在函数有 3 个 asm 助记符:“vfmadd132pd”、“231”和“213”?

    有人可以向我解释一下为什么融合乘法累加指令有 3 种变体 vfmadd132pd vfmadd231pd and vfmadd213pd 而只有一个 C 内在函数 mm256 fmadd pd 为了简单起见 在 AT T 语法中 有什么区别

随机推荐