Write-Combining Buffer位于何处? 86

问题描述 投票:6回答:2

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

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

它是依赖于微架构的吗?

x86 intel cpu-architecture cpu-cache amd-processor
2个回答
7
投票

写缓冲区可以在不同处理器中具有不同目的或不同用途。此答案可能不适用于未明确提及的处理器。我想强调术语“写缓冲区”在不同的上下文中可能意味着不同的东西。这个答案仅适用于Intel和AMD处理器。

Write-Combining Buffers on Intel Processors

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

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中搜索“填充缓冲区”,则可以看到在L1D未命中后分配了行填充缓冲区(LFB)。 LFB在满足L1D未命中时保存数据,但在所有数据准备好写入L1D高速缓存之前。

(2)填充缓冲区在可缓存存储器上分配给L1缓存,并且目标线不处于允许修改的相干状态。我的理解是,对于可缓存存储,只有RFO请求保存在LFB中,但是要存储的数据在存储缓冲区中等待,直到目标行被提取到为其分配的LFB条目中。英特尔优化手册的第2.4.5.2节中的以下声明支持此功能:

L1 DCache可以从分配到退役时保持多达64个负载微操作。它可以从分配维持多达36个存储操作,直到将存储值提交到缓存,或者在非临时存储的情况下写入行填充缓冲区(LFB)。

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

(3)在L1高速缓存中的不可缓存的写组合存储上分配填充缓冲区,而不管该线是在高速缓存中还是在其相干状态。可以在单个LFB中组合和折叠到相同高速缓存行的WC存储(对同一行中的相同位置的多次写入将使得最后一个存储按程序顺序覆盖先前存储在它们变为全局可观察之前)。当前在LFB中分配的请求之间不保持排序。因此,如果有两个WCB正在使用中,则无论先确定哪个WCB将被逐出,无论商店的程序顺序如何。这就是为什么即使所有商店都按顺序退役,WC商店也可能无序地在全球范围内被观察到(尽管WC协议允许WC商店无序提交)。此外,WCB不会被窥探,因此只有当它们到达内存控制器时才会变得全局可观察。更多信息请参见英特尔手册V3中的第11.3.1节。

some AMD processors使用与非临时存储的填充缓冲区分开的缓冲区。 P6中还有许多WCB缓冲区(第一个实现WCB),P4专用于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的情况下的存储器控​​制器)。当请求在缓存中命中时,不会分配填充缓冲区。因此,在高速缓存中直接执行在高速缓存中命中的存储请求,并且从高速缓存直接服务在高速缓存中命中的加载请求。当从缓存中逐出一行时,不分配填充缓冲区。被驱逐的行被写入自己的缓冲区(称为写回缓冲区或逐出缓冲区)。以下是来自英特尔的patent,讨论了针对I / O写入的写入梳理。

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

Write-Combining Buffers on AMD Processors

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

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

“老款AMD处理器”部分让我很好奇。这是在新款AMD处理器上有所改变吗?在我看来,在包括最新的17h系列处理器(Zen)在内的所有新款AMD处理器上都是如此。关于Zen mircoarchitecture的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和所有后来的处理器。不幸的是,没有任何关于扮演英特尔填充缓冲区角色的AMD缓冲区的说法。


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


7
投票

在现代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和内存来说,离开核心可能并没有太大的不同;只是在核心之间的环/网状互连上发送不同类型的消息;在英特尔CPU中,内存控制器是just another stop on the ring bus(在“系统代理”中),就像其他具有L3片段的内核一样.@BeeOnRope suggests,L1 LFB并没有真正直接连接到环形总线,并且请求不放置数据进入L2可能仍然通过L2超级缓冲区到环形总线/网格。这似乎很可能,因此每个核心只需要在环形总线上存在一个点,并且L2和L1之间的仲裁发生在核心内部。


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

当正常存储数据从L1d逐出时,正常存储数据进入LFB,或者为分配新线路或者响应来自想要读取该线路的另一个核心的RFO腾出空间。

在L1d中丢失的正常负载(和存储)需要高速缓存来获取该行,该行还分配LFB以跟踪进入的线路(以及对L2的请求)。当数据到达时,它会直接发送到等待它的加载缓冲区,与将其放入L1d并行。 (在CPU体系结构术语中,请参阅"early restart" and "critical word first":缓存未命中仅阻塞,直到所需数据到达,其余缓存行“在后台”到达。)您(以及英特尔的CPU架构师)绝对不希望L2命中延迟包括将数据放入L1d并再次将其取回。

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

© www.soinside.com 2019 - 2024. All rights reserved.