【问题标题】:micro-benchmark to study the latency of movdir64b instruction用于研究 movdir64b 指令延迟的微基准测试
【发布时间】:2021-05-20 00:13:24
【问题描述】:

我想在支持该指令的系统上研究指令movdir64b 的延迟。

我如何编写一个简单的微基准来实现这一点?

注意:MOVDIR64B 从源内存地址读取 64 字节,并对目标地址执行 64 字节直接存储操作。 [详情:https://www.felixcloutier.com/x86/movdir64b]

【问题讨论】:

    标签: x86 intel cpu-architecture instruction-set microbenchmark


    【解决方案1】:

    (来自 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 个字节开始,其中包含指向自身的指针。)

    【讨论】:

    • 感谢您的回答。我是编写和运行汇编代码的新手。所以让我退后一点。您能否详细说明“将其放入静态可执行文件”部分?在我的系统上运行这个(或任何其他)汇编代码的最简单方法是什么?
    • 是的,我正在查看您指出的用例(MMIO 写入加速器设备)。
    • @Rajesh: Can x86's MOV really be "free"? Why can't I reproduce this at all? 显示了一些完整的源代码和构建/运行命令示例,RDTSCP in NASM always returns the same value (timing a single instruction) 也是如此。如果您增加迭代次数足以隐藏更多的启动开销,您可以从正常构建的程序内部测试相同的循环,或者围绕调用执行此操作的函数进行手动计时,或者如果您不关心的话主要使用性能计数器来计时此代码,而不是启动开销。
    • @Rajesh:那么你想测量什么延迟?从什么到什么?源数据在内存中准备好做什么,正在发送网络数据包?
    • 我正在尝试测量平均 movdir64b 指令从源位置读取数据并将数据放入目标位置所需的时间。我假设这条指令有助于多个内核通过 CXL 向主机/设备内存读取/写入数据,我的理解有什么差距吗?
    最近更新 更多