【问题标题】:Where is the Write-Combining Buffer located? x86写组合缓冲区在哪里? x86
【发布时间】:2018-10-02 06:03:39
【问题描述】:

Write-Combine 缓冲区是如何物理连接的?我已经看到了说明许多变体的框图:

  • L1 和内存控制器之间
  • CPU 的存储缓冲区和内存控制器之间
  • CPU 的 AGU 和/或存储单元之间

它是否依赖于微架构?

【问题讨论】:

  • 在 Intel CPU 中,它是 LFB(行填充缓冲区),也用于来自 L1 L2 的其他未决传输。这就是为什么英特尔建议在进行 NT 存储时避免过多的其他流量,以避免部分填充的 LFB 过早刷新。 software.intel.com/en-us/articles/…
  • 你无处不在,彼得 :) 谢谢你提到 line-fill-buffers,这是我第一次听说它们。

标签: x86 intel cpu-architecture cpu-cache amd-processor


【解决方案1】:

写缓冲区在不同的处理器中可以有不同的用途或不同的用途。此答案可能不适用于未特别提及的处理器。我想强调的是,“写缓冲区”一词在不同的上下文中可能意味着不同的东西。此答案仅与 Intel 和 AMD 处理器有关。

英特尔处理器上的写入组合缓冲区

每个缓存可能伴随着零个或多个行填充缓冲区(也称为填充缓冲区)。 L2 的填充缓冲区集合称为超级队列或超级队列(超级队列中的每个条目都是一个填充缓冲区)。如果高速缓存在逻辑核心或物理核心之间共享,那么相关的填充缓冲区也会在核心之间共享。每个填充缓冲区可以保存一个高速缓存行和描述高速缓存行(如果它被占用)的附加信息,包括高速缓存行的地址、内存类型和一组有效位,其中位数取决于跟踪高速缓存行的各个字节。在早期的处理器(例如Pentium II)中,只有一个填充缓冲区能够进行写组合(和写折叠)。随着处理器的更新,行缓冲区的总数和能够进行 write-combing 的缓冲区的总数稳步增加。

Nehalem 到 Broadwell 的每个 L1 数据缓存都包含 10 个填充缓冲区。 Core 和 Core2 每个物理内核有 8 个 LFB。根据this,Skylake 上有 12 个 LFB。 @BeeOnRope 观察到 Cannon Lake 上有 20 个 LFB。我在手册中找不到明确的声明,说明 LFB 在所有这些微架构上都与 WCB 相同。然而,英特尔的人写的这个article 说:

请参阅英特尔® 64 和 IA-32 架构优化参考 特定处理器中填充缓冲区数量的手册; 通常数字是 8 到 10。请注意,有时这些也是 称为“写入组合缓冲区”,因为在一些较旧的 仅支持处理器流式存储。

我认为 LFB 一词最初是由英特尔在英特尔酷睿微架构中引入的,在该微架构上,所有 8 个 LFB 也是 WCB。基本上,英特尔当时偷偷地将 WCB 重命名为 LFB,但此后并未在其手册中对此进行说明。

同样的引用还说,WCB 一词用于较旧的处理器,因为它们不支持流式加载。这可以解释为 LFB 也被流式加载请求 (MOVNTDQA) 使用。但是,第 12.10.3 节说流式加载将目标行提取到称为流式加载缓冲区的缓冲区中,这在物理上显然与 LFB/WCB 不同。

在以下情况下使用行填充缓冲区:

(1) 在缓存中的加载未命中(请求或预取)时分配填充缓冲区。如果没有可用的填充缓冲区,加载请求会不断堆积在加载缓冲区中,这最终可能导致问题阶段停止。在加载请求的情况下,分配的填充缓冲区用于临时保存来自内存层次结构较低级别的请求行,直到它们可以写入缓存数据阵列。但是,即使该行尚未写入高速缓存数据阵列,仍可将所请求的高速缓存行部分提供给目标寄存器。根据Patrick Fay (Intel)

如果您在 PDF 中搜索“填充缓冲区”,您会看到该行 填充缓冲区 (LFB) 在 L1D 未命中后分配。 LFB持有 数据,以满足 L1D 未命中但在所有数据之前 准备写入 L1D 缓存。

(2) 一个填充缓冲区被分配到 L1 缓存的可缓存存储上,并且目标行不处于允许修改的一致性状态。我的理解是,对于可缓存的存储,只有 RFO 请求保存在 LFB 中,但要存储的数据在存储缓冲区中等待,直到目标行被提取到为其分配的 LFB 条目中。 Intel 优化手册第 2.4.5.2 节中的以下语句支持这一点:

L1 DCache 可以从分配中维护多达 64 个加载微操作 直到退休。它可以维持多达 36 家商店的运营,从 分配,直到存储值提交到缓存,或写入 在非临时存储的情况下到行填充缓冲区 (LFB)。

这表明如果目标行不在 L1D 中,则不会将可缓存存储提交到 LFB。换句话说,存储必须在存储缓冲区中等待,直到目标行写入LFB,然后在LFB中修改该行,或者将目标行写入L1D,然后修改该行在 L1D 中。

(3) 填充缓冲区分配在 L1 高速缓存中不可高速缓存的写入组合存储上,无论该行是否处于高速缓存或其一致性状态。可以在单个 LFB 中组合和折叠到同一缓存行的 WC 存储(多次写入同一行中的同一位置将使程序顺序中的最后一个存储在它们成为全局可观察之前覆盖以前的存储)。当前在 LFB 中分配的请求之间不维护排序。因此,如果有两个 WCB 正在使用中,则不能保证哪个将首先被驱逐,而不管存储的顺序与程序顺序无关。这就是为什么 WC 存储可能会变得全局可观察到无序,即使所有存储都按顺序退役(尽管 WC 协议允许 WC 存储无序提交)。此外,WCB 不会被窥探,因此只有在它们到达内存控制器时才成为全局可观察的。更多信息可以在英特尔手册 V3 的第 11.3.1 节中找到。

some AMD processors 使用与非临时存储的填充缓冲区分开的缓冲区。 P6(第一个实现 WCB)和 P4 中也有许多 WCB 缓冲区,专用于 WC 内存类型(不能用于其他内存类型)。在 P4 的早期版本中,有 4 个这样的缓冲区。对于支持超线程的 P4 版本,当启用超线程并且两个逻辑核心都在运行时,WCB 会在两个逻辑核心之间进行静态分区。然而,现代英特尔微架构竞争性地共享所有 LFB,但我认为至少为每个逻辑内核保留一个可用以防止饥饿。

(4) L1D_PEND_MISS.FB_FULL 的文档表明 UC 存储分配在相同的 LFB 中(无论该行是处于缓存还是其一致性状态)。与可缓存存储类似,但与 WC 不同的是,UC 存储不会在 LFB 中合并。

(5) 我通过实验观察到来自INOUT 指令的请求也在LFB 中分配。如需更多信息,请参阅:How do Intel CPUs that use the ring bus topology decode and handle port I/O operations

其他信息:

填充缓冲区由缓存控制器管理,该控制器连接到其他级别的其他缓存控制器(或在 LLC 的情况下连接到内存控制器)。当请求命中缓存时,不会分配填充缓冲区。因此,在缓存中命中的存储请求直接在缓存中执行,而在缓存中命中的加载请求则直接从缓存中提供服务。当从缓存中逐出行时,不会分配填充缓冲区。逐出的行被写入它们自己的缓冲区(称为写回缓冲区或逐出缓冲区)。这是来自 Intel 的 patent,它讨论了 I/O 写入的写入组合。

我进行了一项与我在here 中描述的非常相似的实验,以确定是否分配了单个 LFB,即使同一行有多个负载也是如此。事实证明,情况确实如此。第一次加载到回写 L1D 缓存中未命中的行会获得为其分配的 LFB。所有后来加载到同一缓存行的内容都被阻止,并且在其相应的加载缓冲区条目中写入一个块代码,以指示它们正在等待该 LFB 中保存的同一请求。当数据到达时,L1D 缓存向加载缓冲区发送一个唤醒信号,并且在该行上等待的所有条目都被唤醒(解除阻塞)并计划在至少一个加载端口可用时将其发送到 L1D 缓存.显然,内存调度程序必须在未阻塞的负载和刚刚从 RS 分派的负载之间进行选择。如果在所有等待的负载有机会得到服务之前,由于任何原因该线路被驱逐,那么它们将再次被阻塞,并且将再次为该线路分配 LFB。 store case我没有测试过,但是我觉得不管是什么操作,都是为一行分配一个LFB。 LFB 中的请求类型可以从预取提升到需求加载,再到推测 RFO 到需要时的需求 RFO。我还凭经验发现,在刷新管道时,不会删除从错误预测路径上的 uops 发出的推测性请求。它们可能会被降级为预取请求。我不知道。

AMD 处理器上的写入组合缓冲区

我之前根据article 提到,有一些 AMD 处理器使用与非临时存储的填充缓冲区分开的缓冲区。我从文章中引用:

在较旧的 AMD 处理器(K8 和 Family 10h)上,非临时存储 使用一组四个独立的“写组合寄存器” 用于 L1 数据缓存未命中的八个缓冲区中的一个。

“在较旧的 AMD 处理器上”部分让我很好奇。这在较新的 AMD 处理器上是否发生了变化?在我看来,所有较新的 AMD 处理器(包括最新的 Family 17h 处理器 (Zen))仍然如此。 Zen 微架构上的 WikiChip article 包括两个提到 WC 缓冲区的数字:thisthis。在第一个图中,不清楚 WCB 是如何使用的。然而,在第二个中,很明显显示的 WCB 确实专门用于 NT 写入(WCB 和 L1 数据缓存之间没有连接)。第二个数字的来源似乎是这些slides1。我认为第一个数字是由 WikiChip 制作的(这解释了为什么 WCB 被置于不确定的位置)。事实上,WikiChip 文章并未提及 WCB。但是,我们可以通过查看Software Optimization Guide for AMD Family 17h Processors 手册中的图 7 和用于 Family 17h 处理器的加载和存储队列的patent 来确认所示的 WCB 仅用于 NT 写入。 AMD 优化手册指出,现代 AMD 处理器中每个内核有 4 个 WCB。我认为这适用于 K8 和所有后续处理器。不幸的是,没有提及扮演 Intel 填充缓冲区角色的 AMD 缓冲区。


1迈克尔·克拉克,A New, High Performance x86 Core Design from AMD,2016 年。

【讨论】:

  • 好答案。可能值得注意的是,因为这是英特尔特有的问题,英特尔喜欢将其填充缓冲区/队列从 L2 称为更高级别的缓存“超级队列”。我认为他们将这个术语用于 L2 L3 和 L3 内存路径,因为实际上 L3 和内存控制器在环形总线上处于相同的层次结构级别(当然还有内存控制器本身还有更多队列)。
  • 是的,超级队列可能会做更多的事情,但我的意思是,您将每一级缓存描述为具有填充缓冲区,虽然这对于一般描述可能是正确的,但英特尔专门使用了术语 行填充缓冲区 用于 L1 L2 缓冲区。对于除此之外的排队/缓冲机制,特别是管理 L2 未命中和与环形缓冲区通信的机制,当他们给它一个名字时,它们指的是超级队列。
  • 这种区别很重要,因为您想知道英特尔在优化手册中提到的确切缓冲区,尤其是在查看性能事件名称时。 “填充缓冲区”和“超级队列”都出现在事件名称中,在这些情况下,它们谈论的是内存路径的非常具体的部分,如上所述。这两个队列也有不同的大小(通常分别为 LFB 和 SQ 分别为 10 和 16),这有时很重要。
  • @BeeOnRope 我添加了一个脚注来提及超级队列的事情。随意编辑答案。
  • @Noah 该声明不是在谈论分组或组合存储,而是说对于任何类型的请求,都为其分配一个 LFB 以供进一步处理。因此,LFB 作为一种资源,被所有类型的请求使用。
【解决方案2】:

在现代 Intel CPU 中,写入组合由 LFB(行填充缓冲区)完成,也用于来自 L1 L2 的其他未决传输。每个核心有 10 个(从 Nehalem 开始)。 (Transfers between L2 and L3 use different buffers, called the "superqueue")。

这就是为什么英特尔建议在进行 NT 存储时避免过多的其他流量,以避免由于分配 LFB 的需求负载而导致部分填充的 LFB 过早刷新。 https://software.intel.com/en-us/articles/copying-accelerated-video-decode-frame-buffers

LFB 的“内部”连接到 L1d、存储缓冲区和加载端口。

LFB 的“外部”可以与 L2 通信,或者(可能在 L2 的帮助下)通过环形总线/网格连接到内存控制器,或 L3 进行 NT 预取。对于 L3 与内存而言,离核可能并没有太大区别。只是在核心之间的环/网状互连上发送不同类型的消息;在 Intel CPU 中,内存控制器是 just another stop on the ring bus(在“系统代理”中),就像其他带有 L3 切片的内核一样。@BeeOnRope suggests L1 LFB 并不是真正直接连接到环总线,并且不将数据放入 L2 的请求可能仍会通过 L2 超级队列缓冲区到达环形总线/网格。这似乎很可能,因此每个核心只需要环形总线上的一个存在点并在它们之间进行仲裁L2 和 L1 发生在内核内部。


NT 存储数据 直接从存储缓冲区进入 LFB,并探测 L1d 以查看它是否需要先驱逐该行。

普通存储数据在 LFB 被从 L1d 逐出时进入 LFB,以便为分配的新行腾出空间,或者响应另一个内核想要读取该行的 RFO。 p>

正常加载(和存储)在 L1d 中未命中需要缓存来获取该行,这还分配一个 LFB 来跟踪传入行(以及对 L2 的请求)。当数据到达时,它被直接发送到等待它的加载缓冲区,同时将它放置在 L1d 中。 (在 CPU 架构方面,请参阅"early restart" and "critical word first":缓存未命中只会阻塞,直到需要的数据到达,缓存行的其余部分“在后台”到达。)您(和英特尔的 CPU 架构师)绝对不想要L2 达到延迟,包括将数据放入 L1d 并再次将其取出。

NT 加载从 WC 内存 (movntdqa) 直接从 LFB 读取;数据根本不会进入缓存。 LFB 已经连接到负载端口以提前重启正常负载,因此我认为 SSE4 能够添加movntdqa 而无需大量额外的芯片成本。特殊之处在于,未命中只会直接从内存中填充 LFB,绕过 L3/L2/L1。 NT 存储已经需要 LFB 才能与内存控制器通信。

【讨论】:

  • 嘿彼得。很棒的答案。如果我可能会问,LFB 然后用于装载和存储?根据数据进入LFB的方式,它决定了它的发送方式? IE。允许 NT 存储数据:存储缓冲区 -> LFB -> mem.controller。与普通商店:L1D -> L2。
  • @Kay:请记住,L1d 是回写式缓存,因此脏数据不会立即刷新。但是当它最终被刷新时,是的,我认为它是 L1d -> LFB -> L2。 (并且可以在 L2 中处于修改状态,直到从那里被驱逐并写回 L3。)我不能 100% 确定 L1d -> L2 需要 LFB,但肯定是 L1d 中的突出负载缺失。我读过的所有内容都清楚地表明 LFB 会限制负载的内存并行性。 (相关:Why is Skylake so much better than Broadwell-E for single-threaded memory throughput?
  • LFB 的“外部”可能永远不会与内存控制器通信。它可能只是与一些受 L2 和超级队列支持的仲裁组件对话,或者它可能直接与 L2 和超级队列对话。如果 L2 未命中,请求会转到超级队列,LFB 会坐在那里直到它返回。对于 NT 加载(预取),请求的标记可能略有不同,因此它不会被放入 L2(并且可以由 L3 以不同方式处理)。然后超级队列在 L3 被探测时保存请求,如果在访问 DRAM 时也未命中。
  • 这是一个很好的答案,但它只是开始谈论行填充缓冲区,而 OP 询问了写入组合缓冲区。应该在它们之间建立一些联系。据我所知,在过去十年左右的英特尔芯片中(至少从 Sandy Bridge 开始,也许更早),根本没有 WC 缓冲区这样的东西。 WC 缓冲区的功能已完全被 LFB 所包含,LFB 具有更广泛的功能,处理从 L1 向外的所有数据移动,包括常规加载和存储。
  • @BeeOnRope:措辞来自“WC 缓冲区在哪里?它是行填充缓冲区。”从这个开始作为评论删除了不明显的代词剩余,感谢您指出答案的开始可能不应该是与问题的对话。
【解决方案3】:

L1 缓存中有许多缓冲区。

This patent 提供以下缓冲区类型:

  • 窥探缓冲区(服务于来自其他内核的 M/E 状态窥探的缓冲区(读取/RFO))
  • 回写缓冲区(服务于 L1 的 M 状态驱逐的缓冲区)
  • 行填充缓冲区(服务于可缓存加载/存储 L1 未命中的缓冲区)
    • 读取缓冲区(可缓存临时负载的服务 L1 读取未命中)
    • 写入缓冲区(可缓存临时存储的服务 L1 写入未命中)
    • 写入组合行填充缓冲区(不确定,似乎与本专利中的写入组合专用缓冲区相同)
  • 专用缓冲区(服务于不可缓存的加载/存储的缓冲区,“专用”用于从内存而不是 L2 获取(但仍通过 L2 传递请求),并且不填充缓存行)
    • 非写入组合专用缓冲区(服务 UC 加载/存储和 WP 存储)
    • 编写组合专用缓冲区(服务 USWC 加载/存储)

该专利建议这些都可以是同一个物理缓冲区的功能,或者它们可以在物理上是独立的,并且每个功能都有一组缓冲区。在 Intel 上,Skylake 上的 12 个 LFB 可能全部存在,并且逻辑功能在它们之间通过类型或状态字段共享。在一些实施例中,行填充缓冲器还可以处理USWC加载/存储。在一些实施例中,专用缓冲区可以处理未命中 L1 的可高速缓存非临时 (NT) 加载/存储(使得它们不会“填充”L1d 高速缓存,就像名称所暗示的那样,利用 NT 提示来防止高速缓存污染) .

这里的“写组合缓冲区”意味着 USWC 内存/非临时性和固有的弱排序和不可缓存性,但实际的词“写组合”并不意味着任何这些东西,并且可能只是一个常规的概念对同一存储缓冲区的写入未命中被压缩并按程序顺序写入同一行填充缓冲区。 A patent 建议使用此类功能,因此未标记为 WC 的常规时间写入缓冲区可能具有组合功能。相关:Are write-combining buffers used for normal writes to WB memory regions on Intel?

x86-64 优化手册状态(大量赠品):

在一级缓存写入未命中时,它允许多个存储到同一个 在从缓存/内存层次结构中更远的地方读取该缓存行以获取所有权 (RFO) 之前,该缓存行将发生。然后读取行的其余部分,并将尚未写入的字节与未修改的字节组合在一起 返回线。存储顺序和可见性也是写入组合的重要问题。当对先前未写入的高速缓存行的写入组合缓冲区进行写入时,将发生读取所有权 (RFO)。如果后续写入发生在另一个写入组合缓冲区,则可能会为该高速缓存行导致单独的 RFO。对第一个高速缓存行和写入组合缓冲区的后续写入将被延迟,直到第二个 RFO 得到服务,以保证写入的正确排序可见性。如果写入的内存类型是write-combining,则不会有RFO,因为该行没有被缓存,也没有这样的延迟。

这是术语“写组合缓冲区”被用来描述具有纯粹组合能力的常规写缓冲区的明显证据,其中保持强排序。我们现在还知道,分配写入组合缓冲区的不仅仅是非临时存储到任何内存,而是所有写入(因为非临时存储不发出 RFO)。缓冲区用于在 RFO 发生时组合写入,以便可以完成存储并释放存储缓冲区条目(如果它们都写入同一高速缓存行,则可能是多个)。无效位表示在到达 E 状态时要合并到高速缓存行中的位。一旦该行出现在缓存中,LFB 就可以转储到缓存中,之后对该行的所有写入都可以直接写入缓存行,或者可以保持分配状态以加快进一步的读/写,直到发生释放条件(例如,它需要用于其他目的或 RFO 到达线路,这意味着它需要写回线路)

所以现在看来​​,所有缓冲区都可以是任何类型的逻辑缓冲区,并且所有逻辑写入缓冲区都是写入组合缓冲区(除非 UC),并且缓存类型决定了缓冲区在弱/强排序方面的处理方式以及是否执行 RFO 或是否将其写回缓存。 LFB 中的缓存类型,要么来自 TLB(它从 PMH 获取缓存类型,分析 PTE、PAT MSR 和 MTRR MSR 并计算最终缓存类型),要么来自缓冲后的 SAB(存储地址缓冲区)推测性 TLB 查找的结果。

所以现在有 6 种类型的缓冲区:

  • 写入组合 LFB(WB 写入未命中/预取)
  • 读取 LFB(从 UC 和 USWC 以外的任何地方读取未命中/预取)
  • 写入组合专用缓冲区(WP 写入、WT 写入未命中、USWC 读取/写入、NT 读取/写入到 UC 以外的任何位置)
  • 专用缓冲区(UC 读/写)
  • 窥探缓冲区
  • 逐出写回缓冲区

这些缓冲区由物理地址索引,并与 L1 缓存并行扫描,如果它们包含有效数据,则可以更快、更有效地满足读/写命中,直到它们在释放条件发生时被释放。我认为“10 LFB”值是指可用于前两个目的的缓冲区数量。 L1d 回写有一个单独的 FIFO 队列。

我们不要忘记缓存类型的优先顺序:

  • UC(英特尔 E 位)
  • USWC (PAT)
  • UC (MTRR)
  • UC (PAT)
  • USWC (MTRR)(如果与 WP 或 WT (PAT/MTRR) 结合使用:逻辑和或非法:默认为 UC)
  • UC- (PAT)
  • WT WP (PAT/MTRR)(在此级别中组合 MTRR 会产生逻辑和内存类型;在此级别上组合 MTRR 和 PAT 会产生逻辑和(英特尔);AMD(非法:UC))
  • WB (PAT/MTRR)

此处的 MTRR 包括范围未由 MTRR 映射的默认类型。 MTRR 是由 MTRR 解决了任何冲突或默认值而产生的最终类型。首先,将默认值解析为 UC 并与任何 UC MTRR 排名相同,然后将任何冲突的 MTRR 组合成最终的 MTRR。然后将此 MTRR 与 PAT 和 E 位进行比较,具有最高优先级的成为最终的内存类型,尽管在某些情况下,它们是非法组合,会导致创建不同的类型。没有 UC-MTRR。

缓存类型说明(时间):

  • UC(强不可缓存)。不允许推测性读取和写入组合。有条不紊。
  • UC-(弱不可缓存)与 UC 相同,只是它是 PAT 的较低优先级 UC
  • 允许 USWC(不可缓存的推测性写入组合)推测和写入组合。读取和写入不会被缓存。相对于其他读写而言,读写都变得弱排序。
  • WT(直写)读取是可缓存的,其行为类似于 WB。命中 L1 缓存的 WT 写入同时更新 L1 缓存和外部存储器,而未命中 L1 缓存的 WT 写入仅更新外部存储器。允许推测性读取和写入组合。有条不紊。
  • WP(写保护)读取是可缓存的,其行为类似于 WB。写入不可缓存并导致行无效。允许推测性读取。有条不紊。
  • WB(回写)一切都是允许的。有条不紊。

缓存类型说明(非临时):

  • NT UC 没有区别(UC 覆盖)
  • 我认为 NT USWC 与 USWC 没有区别
  • NT WT 我认为这与 NT WB 的行为相同。 Seems so
  • NT WP 我不确定 WP 是否会覆盖 NT 提示以进行仅写入或读取。如果它不覆盖读取,那么读取的行为很可能类似于 NT WB。
  • NT WB 在答案顶部的专利中,NT 读取可以命中 L1 缓存,并且它使用有偏的 LRU 策略来减少污染(这就像强制集合的树 PLRU 指向那个方向)。读取未命中的行为类似于 USWC 读取未命中,并且分配了一个写入组合专用缓冲区,它会导致 LLC 或其他内核或套接字中的任何别名行在从内存读取行之前被写回内存,并且读取也是弱排序的。对于 NT WB 读取在现代英特尔 CPU 上发生的情况,它是特定于实现的——NT 提示可以完全忽略,它的行为类似于WB (see full discussion)。 L1 缓存in some implementations 中的写入命中可以将写入与 L1 中的行与强制 PLRU 合并,以便接下来将其逐出(作为 WB),或者写入命中导致逐出,然后将写入组合专用缓冲区分配为如果有未命中,则在解除分配条件下将其写回为 USWC(使用WCiL(F))。写未命中分配一个专用的写组合缓冲区,并在释放时作为 USWC 写回内存,但如果该未命中导致 L2 命中,则写组合缓冲区立即或在释放条件下写入 L2,这会导致立即从 L2 逐出,或者它强制 PLRU 位,因此它是下一个逐出。缓冲区继续满足对行的进一步读/写,直到它被释放。 NT 写入是弱排序的。未处于 M/E 状态的 L1/L2 中的写入命中仍可能导致 WiL 使当前和其他套接字上的所有其他内核无效以获得 E 状态,否则,它只会使该行无效并且当最终创建 USWC 存储时,LLC 会检查当前或远程套接字上的任何其他内核是否需要失效。

如果完整的 USWC 存储(操作码 WCiLF)在 LLC 缓存中命中,则 Cbo 将 IDI 无效(由于某种原因,由 Cbo 发送的无效 IDI 操作码 (as part of egress request in the IPQ logical queue of the TOR) 未记录)发送到所有内核,并附上副本和also always sends a QPI InvItoE 无论是否有 LLC 未命中,都根据 SAD 交错规则发送到正确的本地代理。存储只有在过滤器中的所有核心都响应失效并且本地代理也响应时才会发生;在他们响应之后,Cbo 从 L2 发送数据的WrPull_GO_I(代表具有全局观察通知和 Invalidate Cache Line 的 Write Pull)并将数据发送到家。如果部分 USWC 存储 WCiL 在 LLC 缓存中命中,则会发生同样的情况,除非该行现在在 LLC 切片中被修改(从 SnpInv 它发送而不是如果该行仅存在于一个内核中则无效--我猜它确实这样做了,并且不只是像WCiLF那样为WCiL发送简单的无效信息)或者一直在LLC中进行修改,Cbo执行WBMtoI/WbMtoIPtl在为 USWC 存储执行写使能位写回WcWrPtl 之前发送给本地代理。 PAT 对虚拟地址进行操作,因此可能会出现别名,即同一个物理页面可以有多个不同的缓存策略。据推测,WP 写入和 UC 读/写别名也具有相同的行为,但我不确定。

核心超级队列是 L2 和 L3 之间的接口。 SQ 也称为“非核心请求缓冲区”,任何非核心请求都称为已到达 SQ 的任何 请求。虽然,我相信条目被分配用于在 L1 回写时填充 L2,这并不是真正的“请求”。因此,OFFCORE_REQUESTS_BUFFER.SQ_FULL 可能发生在 L1D 回写挂起的 FIFO 请求缓冲区已满时,这表明如果该缓冲区已满,则无法分配 SQ 中的另一个条目,这表明条目同时在 SQ 和该缓冲区中分配.对于 LFB,在 L2 命中时,数据直接提供给 LFB,否则在未命中时,如果分配 SQ 条目并在从两个 32B IDI 事务获取的数据写入 SQ 时提供给 LFB。进一步的 L2 未命中可能会命中 SQ 并被压缩到同一个条目 (SQ_MISC.PROMOTION)。

RFO 意图从存储缓冲区开始,如果它以 M 或 E 状态命中 L1d 缓存,则执行写入并结束 RFO。如果线路处于 I 状态,则分配 LFB 并将 RFO 传播到 L2,如果存在 M 或 E 状态,则可以在那里满足(当 M 线路写回 L2 时,它变为 M 状态关于L3)。如果它是 I 状态/不存在,则在 SQ 中分配它,并且 RFOItoM 数据包传播到处理地址范围的相应 LLC 切片 Cbo。然后,Cbo 切片使用 snoop 过滤器使其他核心无效,这涉及向核心发送无效请求(或窥探无效 (SnpInv),如果它只存在于一个核心中 - 它也会获取数据,因为 Cbo不知道这是否被修改)。 Cbo 一直等待,直到它收到来自内核的无效确认(以及如果修改的数据)。然后 Cbo 向请求核心的 SQ 指示它现在具有独占访问权限。它可能会提前确认这一点,因为 Cbo 可能必须从内存控制器中获取数据,因此它可以提前确认数据不存在于任何其他内核中。 SQ 将此信息传播到 L1d 缓存,这会导致在 LFB 中设置全局观察位,并且高级存储现在可以从 SAB/SDB 退出以释放其条目。当数据最终到达时,它被传播到 LFB,在那里它被合并到无效位中,然后根据该地址的释放条件或由于 LFB 资源限制将其写入缓存。

如果 WB 行存在于 L1 中但处于 S 状态,它可能会或可能不会分配 LFB 来合并存储,然后才能写入该行。如果它在 L1 中无效/不存在,则将 LFB 分配给合并存储。然后,如果线路存在于 L2 中但处于 S 状态,则将WiL 数据包发送到 LLC 切片(它只需要使其他内核无效)。然后它通知请求核心的 SQ,它现在可以将其转换为 E 状态。此信息会传播到 L1d 缓存,现在可以在 LFB 资源约束地址的释放条件发生之前将 LFB 合并到缓存中。

ItoM 在假定要写入整行时使用而不是 RFO,因此它不需要行中已有数据的副本,并且如果它已经包含数据任何其他状态(S、E、M)。理论上的StoIWiL 与RFO 相同,对于E 相同,除了I,其中ItoM 和RFO 的不同之处在于LLC 不需要将数据发送到核心一个ItoM。该名称仅强调状态变化。它如何知道整行将被我不知道的存储写入..也许 L1d 缓存可以在分配 LFB 时同时压缩 MOB 中的一堆顺序高级存储,因为 RFO 是立即发送的我认为分配(然后在 RFO 到达后将它们全部退休)。我想在必须生成操作码之前,商店还有一些时间到达 LFB(L2 查找)。 This also might be used by rep stos.

我假设 RFO IDI 数据包不需要区分需求锁定 RFO、预取 RFO、需求常规 RFO(非预取),以对应 Xeon 5500 core events,但可能出于优先目的(优先考虑需求流量over prefetch),否则只有核心需要知道这个信息,这要么编码在RFO 中,要么有单独的未记录的操作码。 PrefRFO 由内核发送,用于预取到 LLC。

L1i 表面上缺少填充缓冲区意味着填充缓冲区的主要好处是存储和组合存储的位置,并且可以更快地释放存储缓冲区条目。由于 L1i 不执行任何存储,因此这不是必需的。我原以为它确实仍然读取了 LFB,以便它可以在填充缓存时或之前提供未命中数据,但后续读取并没有加快,因为我认为缓冲区是 PIPT 并且它们的标签与缓存并行扫描。读取 LFB 还将压缩读取以指向 LFB 并防止多次查找,并通过跟踪 LFB MSHR 中的当前未命中来防止缓存阻塞,因此很可能存在此功能。

【讨论】:

  • 基于 here 完成的测试,我不认为可以在 LFB 中组合的多个可缓存存储即将优化出 RFOItoM(仍然看到高 uncore_read交通)。
  • @Noah 我认为 ItoM 可能只是用于 rep stos 但我不确定
  • ItoMrep movsb/stosb 和 NT 商店使用。不被任何临时存储 AFAIK 使用(也不是 64 字节 zmm 存储或组合 ymm 存储)。
  • @Noah 是的,我打算在某个时候测试这些性能事件..
猜你喜欢
  • 2018-12-06
  • 1970-01-01
  • 1970-01-01
  • 2014-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多