为什么 MASKMOVDQU 没有扩展到 256 位和 512 位存储?

Bee*_*ope 5 x86 caching intel cpu-architecture

MASKMOVDQU 1是86存储指令之间特殊的,因为在原则上,它可以让你各个字节存储在缓存行,而无需首先加载整个高速缓存行一路核心,以便写入的字节可以与不合并- 覆盖现有字节。

它似乎使用与 NT 存储相同的机制来工作:在不首先执行 RFO 的情况下将缓存行向下推。根据英特尔软件开发手册(重点是我的):

MASKMOVQ 指令可用于提高需要逐字节合并数据的算法的性能。它不应导致读取所有权;这样做会产生不必要的带宽,因为将使用字节掩码直接写入数据,而无需在存储之前分配旧数据

然而,与其他 NT 存储不同,您可以使用掩码来指定实际写入的字节。

如果您想在不太可能适合任何级别的缓存的大区域中进行稀疏字节粒度写入,则此指令似乎是个主意。

与几乎所有其他有用的指令不同,英特尔没有将指令扩展到 AVX/AVX2 或 AVX-512 中的 256 或 512 位。这是否表示不再推荐使用此指令,可能无法在当前或未来的架构上有效实现?


1 ...及其在 MMX MASKMOVQ 中的64 位前身。

Pet*_*des 6

MASKMOVDQU确实很慢,而且可能从来都不是一个好主意,比如 Skylake 上每 6 个周期吞吐量 1 个,或者 Zen2 / Zen3 上每 18c 一个。

我怀疑屏蔽 NT 矢量存储不再适用于多核 CPU,因此,如果完整的 64 字节行中有任何未修改的字节,即使是 128 位版本也可能在现代 x86 上无法进行屏蔽写入。

常规(非 NT)屏蔽向量存储在 AVX512 中卷土重来。对 L1d 缓存的屏蔽提交似乎得到了有效支持,并且对于 AVX1vmaskmovps/pd和 Intel CPU 上等效的整数进行双字/四字屏蔽。(虽然不是 AMD:AMD 仅具有高效的屏蔽 AVX1/2 加载,而不是存储。https: //uops.info/table.html显示VPMASKMOVD M256, YMM, YMMZen3 上是 42 uops,12c 吞吐量,与 Zen2 大致相同。与 3 uops, Skylake 上的延迟为 1c。屏蔽负载在 AMD 上很好,1 uop 0.5c 吞吐量,因此实际上比 AVX2 版本的 Skylake 更好。可能 Skylake 内部进行了屏蔽比较,并使用为 AVX-512 设计的硬件。)

AVX512F 使双字/四字粒度的屏蔽成为一等公民,对加载和存储都提供非常有效的支持。AVX512BW 增加了 8 位和 16 位元素大小,包括屏蔽加载/存储,vmovdqu8英特尔硬件也有效支持这一点;即使对于商店来说也是如此。


SDRAM 总线协议确实支持字节屏蔽写入(每个字节有 1 个屏蔽线,作为高速缓存线突发传输的一部分)。 这份英特尔文档(关于 FPGA 或其他内容)包括对DM(数据掩码)信号的讨论,确认 DDR4 仍然具有它们,其功能与维基百科上针对 SDRAM 描述的 DQM 线相同:https://en.wikipedia.org/wiki /Synchronous_dynamic_random-access_memory#SDR_SDRAM。(DDR1 将其更改为仅写入掩码,而不是读取掩码。)

因此,硬件功能已经存在,并且现代 x86 CPU 可能使用它来对不可缓存内存进行单字节写入。

(更新:与某些早期的 SDRAM / DDR 版本不同,字节屏蔽可能在 DDR4 中是可选的。在这种情况下,存储可以以屏蔽形式到达内存控制器,但内存控制器必须读取/修改/写入包含 8 字节块,使用单独的突发读取和突发写入命令到实际 DIMM。对于仅影响部分 64 字节 DDR 突发大小的存储,可以将突发截短,从而节省一些数据带宽,但是仍然存在命令开销并占用内存控制器中的缓冲区空间更长的时间。)


如果我们写入一整行,无 RFO 存储就非常有用:我们只需使该行的其他副本无效并存储到内存中即可。

John “Dr. Bandwidth” McCalpin 表示,普通 NT 存储在填充完整的 64 字节行后进行刷新将使脏行无效,而不会导致脏数据的写回。

因此,屏蔽NT 存储需要使用不同的机制,因为任何屏蔽字节都需要从另一个核心的脏行中获取其值,而不是从 DRAM 中的任何内容中获取。

如果部分行 NT 存储机制效率不高,则添加创建它的新指令是不明智的。我不知道它是否比对线路的一部分进行正常存储效率更高或更低,或者这是否取决于情况和uarch。


它不一定是 RFO,但这意味着当这样的存储到达内存控制器时,它必须获取探听过滤器以确保该行同步,或者可能与来自的旧内容合并在刷新到 DRAM 之前缓存。

或者,CPU 内核可以在向内存层次结构发送整行写入之前执行 RFO 并合并。

当回收尚未写入所有 64 字节的 LFB 时,CPU 确实需要某种机制来刷新部分行 NT 存储,而且我们知道这效率不高。(但我忘记了细节。)但也许这就是maskmovdqu现代 CPU 上的执行方式,要么总是如此,要么如果您保留任何字节未修改。

一项实验或许可以找出答案。


因此 TL:DRmaskmovqdu可能只能在单核 CPU 中有效实现。它起源于带有MMX的Katmai Pentium III maskmovq mm0, mm1;SMP 系统已经存在,但在设计时可能不是该指令的主要考虑因素。SMP 系统没有共享的最后一级缓存,但它们在每个套接字上仍然有私有回写式 L1d 缓存。


小智 1

该描述具有误导性。MASKMOVQ 的非时间方面是,如果您写入整行,它不会生成 RFO。如果您使用屏蔽方面,您仍然需要 RMW,在这种情况下您可以只使用 AVX-512 屏蔽寄存器。