(来自 cmets,显然实际目标是测量在 movdir64b 之后多久可以执行另一个。这是吞吐量,而不是延迟。这回答了关于延迟的问题,假设来源和目标是可缓存的内存区域。)
存储部分是 NT(如 movntps),因此如果延迟很重要,则不应使用它。如果目标缓存行之前存在,它将强制从缓存中驱逐它,因此重新加载将导致缓存未命中一直到 DRAM。
如果您关心(通过此内核)快速重新加载数据,请使用普通的可缓存存储。或者,如果您关心它被另一个内核重新加载,那么另一个内核不得不要求这个内核共享线路(比 L3 缓存命中稍慢)可能比一直到 DRAM 更快。
请注意,预期的用例是 MMIO 写入 PCIe 设备。 (在 Sapphire Rapids(Alder Lake / Golden Cove 的服务器版本)中使用另一个 CPU 功能 ENQCMD,提供了一种更好的方法,让您知道写入是否成功,而无需运行另一个 I/O 指令来检查工作描述符是否提交成功。Phoronix article)
您可以通过一个简单的循环来验证重新加载是否很慢,该循环使存储和重新加载成为循环携带的依赖链的一部分。使用 AVX-512(例如,在同时具有 AVX-512 和 movdir64b 的 Tiger Lake (Willow Cove core uarch) 上),您可以重新加载完整数据并将其存储回源缓冲区,从而创建循环携带的依赖链。
或者您可以使用movdir64b a,b / movdir64b b,a 在交替方向上进行 64 字节的复制。 (然后取循环的平均周期/迭代)。
lea rdi, [rel buf+0]
lea rsi, [rel buf+64]
mov ecx, 10000000
.loop:
movdir64b rdi, [rsi]
movdir64b rsi, [rdi]
dec ecx
jnz .loop
(将其放入静态可执行文件中,并使用perf stat 计时。)
或者您可以重新加载 movdir64b 目标并将该加载结果用作movdir64b 的源地址,从地址输入而不是内存数据输入测试延迟。 (从源数据的前 8 个字节开始,其中包含指向自身的指针。)