- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
MASKMOVDQU 1 在 x86 存储指令中很特殊,因为原则上,它允许您将单个字节存储在缓存行中,而无需先将整个缓存行一直加载到内核,以便写入的字节可以与未覆盖的字节合并现有字节。
它似乎使用与 NT 存储相同的机制来工作:在不首先执行 RFO 的情况下将缓存行向下推。根据英特尔软件开发手册(重点是我的):
The MASKMOVQ instruction can be used to improve performance for algorithms that need to merge data on a byteby-byte basis. It should not cause a read for ownership; doing so generates unnecessary bandwidth since data is to be written directly using the byte-mask without allocating old data prior to the store.
最佳答案
MASKMOVDQU
确实很慢,而且可能永远不是一个好主意,例如 Skylake 每 6 个周期吞吐量 1 个或 Zen2/Zen3 每 18c 一个。
我怀疑掩码 NT 向量存储不再适用于多核 CPU,因此,如果完整的 64 字节行中有任何未修改的字节,那么即使是 128 位版本也可能在现代 x86 上进行掩码写入。
常规(不是 NT)掩码矢量存储在 AVX512 中大受欢迎。似乎可以有效地支持对 L1d 缓存的掩码提交,并且对于使用 AVX1 的 dword/qword 掩码 vmaskmovps/pd
和 Intel CPU 上的整数等价物。 (虽然不是 AMD:AMD 只有有效的屏蔽 AVX1/2 加载,而不是存储。https://uops.info/table.html 显示 Zen3 上的 VPMASKMOVD M256, YMM, YMM
是 42 uops,12c 吞吐量,与 Zen2 大致相同。对比 Skylake 上的 3 uops,1c 延迟。掩码负载在 AMD 上很好,1 uop 0.5c 吞吐量,所以实际上比 AVX2 版本的 Skylake 更好。可能 Skylake 在内部做了一个比较掩码并使用为 AVX-512 设计的硬件。)
AVX512F 使具有 dword/qword 粒度的掩码成为一等公民,对加载和存储都提供非常有效的支持。 AVX512BW 添加了 8 位和 16 位元素大小,包括屏蔽加载/存储,如 vmovdqu8
英特尔硬件也有效支持;单 uop 甚至商店。
SDRAM 总线协议(protocol)确实支持字节屏蔽写入(每字节 1 个屏蔽线作为缓存线突发传输的一部分)。 This Intel doc (关于 FPGA 或其他内容)包括对 DM
的讨论(数据掩码)信号,确认 DDR4 仍然具有它们,其功能与维基百科上描述的 SDRAM 的 DQM 线相同 https://en.wikipedia.org/wiki/Synchronous_dynamic_random-access_memory#SDR_SDRAM . (DDR1 将其更改为仅写掩码,而不是读掩码。)
因此,硬件功能就在那里,例如,大概现代 x86 CPU 使用它来对不可缓存的内存进行单字节写入。
(更新:字节屏蔽 may 只有 optional in DDR4 ,与一些早期的 SDRAM/DDR 版本不同。在这种情况下,存储可以以屏蔽形式到达内存 Controller ,但内存 Controller 必须读取/修改/使用单独的突发读取和突发写入命令将包含的 8 字节块写入实际的 DIMM。对于仅影响 64 字节 DDR 突发大小的一部分的存储,可以将突发缩短,从而节省一些数据带宽,但仍然存在命令开销并在内存 Controller 中占用更长的缓冲区空间。)
如果我们写一个完整的行 无 RFO 商店很棒:我们只是使该行的其他副本无效并存储到内存中。
John "Dr. Bandwidth" McCalpin says正常的 NT 存储在填充完整的 64 字节行后刷新 甚至会使脏的行无效,而不会导致脏数据的写回。
所以被屏蔽的 NT 存储需要使用不同的机制,因为任何被屏蔽的字节都需要从另一个内核的脏行中获取它们的值,而不是从 DRAM 中的任何内容中获取。
如果部分行 NT 存储的机制效率不高 ,添加创建它的新指令是不明智的。我不知道它是否比对生产线的一部分进行普通商店效率更高或更低,或者这是否取决于情况和 uarch。
它不必完全是一个 RFO,但这意味着当这样的存储到达内存 Controller 时,它必须获得监听过滤器以确保行同步,或者可能与来自的旧内容合并在刷新到 DRAM 之前缓存。
或者 CPU 内核可以在发送全行记下之前执行 RFO 和合并
内存层次结构。
在回收尚未写入所有 64 字节的 LFB 时,CPU 确实需要某种机制来刷新部分行 NT 存储,我们知道这效率不高。 (但我忘记了细节。)但也许这就是 maskmovdqu
总是在现代 CPU 上执行,或者如果您保留任何未修改的字节。
一个实验可能会发现。
所以 TL:DR maskmovqdu
可能只在单核 CPU 中有效实现。它起源于带有 MMX 的 Katmai Pentium III maskmovq mm0, mm1
; SMP 系统存在,但在设计该指令时可能不是该指令的主要考虑因素。 SMP 系统没有共享的最后一级缓存,但它们在每个套接字上仍然有私有(private)的回写 L1d 缓存。
关于caching - 为什么 MASKMOVDQU 没有扩展到 256 位和 512 位存储?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54931225/
使用 x86 MASKMOVDQU 指令时,目标处是否必须始终有 16 字节可写内存,即使某些掩码位为零? 例如,假设我使用 MASKMOVDQU 写入地址 0x12345FFC。 0x1234500
MASKMOVDQU 1 在 x86 存储指令中很特殊,因为原则上,它允许您将单个字节存储在缓存行中,而无需先将整个缓存行一直加载到内核,以便写入的字节可以与未覆盖的字节合并现有字节。 它似乎使用与
我是一名优秀的程序员,十分优秀!