我正在为各种英特尔处理器的 lock cmpxchg 指令寻找一些平均延迟的参考。我无法找到关于该主题的任何好的参考资料,任何参考资料都会有很大帮助。
谢谢。
我正在为各种英特尔处理器的 lock cmpxchg 指令寻找一些平均延迟的参考。我无法找到关于该主题的任何好的参考资料,任何参考资料都会有很大帮助。
谢谢。
这方面的好的参考资料很少(如果有的话),因为变化很大。它基本上取决于一切,包括总线速度、内存速度、处理器速度、处理器数量、周围指令、内存栅栏以及很可能月球和珠穆朗玛峰之间的角度......
如果您有一个非常具体的应用程序,例如已知(固定)硬件、操作环境、实时操作系统和独占控制,那么它可能会很重要。在这种情况下,基准测试。如果您对软件运行的位置没有这种级别的控制,那么任何测量实际上都毫无意义。
正如这些答案中所讨论的,锁是使用 CAS 实现的,因此如果您可以使用 CAS 而不是锁(这将需要至少两个操作),它会更快(很明显?只是可能)。
您会发现最好的参考资料是Intel Software Developer's Manuals,但由于存在如此多的变化,它们不会给您一个实际的数字。然而,他们将描述如何获得最佳性能。处理器数据表(例如i7 Extreme Edition的“技术文档”下的数据表)可能会为您提供实际数字(或至少一个范围)。
最好的 x86 指令延迟参考可能包含在Agner 的优化手册中,基于对各种 Intel/AMD/VIA 芯片的实际经验测量,并经常针对市场上最新的 CPU 进行更新。
不幸的是,我没有看到CMPXCHG
指令延迟表中列出的指令,但第 4 页确实指出:
带有 LOCK 前缀的指令有很长的延迟,这取决于缓存组织和可能的 RAM 速度。如果有多个处理器或内核或直接内存访问 (DMA) 设备,则所有锁定的指令都将锁定高速缓存行以进行独占访问,这可能涉及 RAM 访问。一个 LOCK 前缀通常花费超过一百个时钟周期,即使在单处理器系统上也是如此。这也适用于带有内存操作数的 XCHG 指令。
几个月来,我一直在研究指数退避。
CAS 的延迟完全取决于指令是可以从缓存中操作还是必须从内存中操作。通常,给定的内存地址由多个线程(例如,指向队列的条目指针)进行 CAS 处理。如果最近成功的 CAS 是由与当前 CAS 执行器共享缓存的逻辑处理器(L1、L2 或 L3,尽管更高级别当然更慢),那么指令将在缓存上运行并且速度会很快 - a几个周期。如果最近成功的 CAS 是由不与当前执行程序共享缓存的逻辑核心执行的,那么最近的 CASer 的写入将使当前执行程序的缓存行无效,并且需要读取内存 - 这将需要数百个周期。
CAS 操作本身非常快 - 几个周期 - 问题是内存。
您可以使用 AIDA64 软件检查指令延迟(但您无法检查要检查的指令,它有一个硬编码的指令列表)。人们在http://instlatx64.atw.hu/上发布结果
从lock
指令中,AIDA64 验证lock add
指令和(即使没有明确的 lockxchg [mem]
也总是锁定prefix
)。
这里有一些信息。为了比较,我还将为您提供以下说明的延迟:
xchg reg1, reg2
没有锁定;add
到寄存器和内存。如您所见,Haswell-DT 上的锁定指令仅比非锁定内存存储慢 5 倍,Kaby Lake-S 上仅慢 2 倍左右。
LOCK ADD [m8], r8 L: 5.96ns= 17.8c T: 7.21ns= 21.58c
LOCK ADD [m16], r16 L: 5.96ns= 17.8c T: 7.21ns= 21.58c
LOCK ADD [m32], r32 L: 5.96ns= 17.8c T: 7.21ns= 21.58c
LOCK ADD [m32 + 8], r32 L: 5.96ns= 17.8c T: 7.21ns= 21.58c
LOCK ADD [m64], r64 L: 5.96ns= 17.8c T: 7.21ns= 21.58c
LOCK ADD [m64 + 16], r64 L: 5.96ns= 17.8c T: 7.21ns= 21.58c
XCHG r8, [m8] L: 5.96ns= 17.8c T: 7.21ns= 21.58c
XCHG r16, [m16] L: 5.96ns= 17.8c T: 7.21ns= 21.58c
XCHG r32, [m32] L: 5.96ns= 17.8c T: 7.21ns= 21.58c
XCHG r64, [m64] L: 5.96ns= 17.8c T: 7.21ns= 21.58c
ADD r32, 0x04000 L: 0.22ns= 0.9c T: 0.09ns= 0.36c
ADD r32, 0x08000 L: 0.22ns= 0.9c T: 0.09ns= 0.36c
ADD r32, 0x10000 L: 0.22ns= 0.9c T: 0.09ns= 0.36c
ADD r32, 0x20000 L: 0.22ns= 0.9c T: 0.08ns= 0.34c
ADD r8, r8 L: 0.22ns= 0.9c T: 0.05ns= 0.23c
ADD r16, r16 L: 0.22ns= 0.9c T: 0.07ns= 0.29c
ADD r32, r32 L: 0.22ns= 0.9c T: 0.05ns= 0.23c
ADD r64, r64 L: 0.22ns= 0.9c T: 0.07ns= 0.29c
ADD r8, [m8] L: 1.33ns= 5.6c T: 0.11ns= 0.47c
ADD r16, [m16] L: 1.33ns= 5.6c T: 0.11ns= 0.47c
ADD r32, [m32] L: 1.33ns= 5.6c T: 0.11ns= 0.47c
ADD r64, [m64] L: 1.33ns= 5.6c T: 0.11ns= 0.47c
ADD [m8], r8 L: 1.19ns= 5.0c T: 0.32ns= 1.33c
ADD [m16], r16 L: 1.19ns= 5.0c T: 0.21ns= 0.88c
ADD [m32], r32 L: 1.19ns= 5.0c T: 0.22ns= 0.92c
ADD [m32 + 8], r32 L: 1.19ns= 5.0c T: 0.22ns= 0.92c
ADD [m64], r64 L: 1.19ns= 5.0c T: 0.20ns= 0.85c
ADD [m64 + 16], r64 L: 1.19ns= 5.0c T: 0.18ns= 0.73c
LOCK ADD [m8], r8 L: 4.01ns= 16.8c T: 5.12ns= 21.50c
LOCK ADD [m16], r16 L: 4.01ns= 16.8c T: 5.12ns= 21.50c
LOCK ADD [m32], r32 L: 4.01ns= 16.8c T: 5.12ns= 21.50c
LOCK ADD [m32 + 8], r32 L: 4.01ns= 16.8c T: 5.12ns= 21.50c
LOCK ADD [m64], r64 L: 4.01ns= 16.8c T: 5.12ns= 21.50c
LOCK ADD [m64 + 16], r64 L: 4.01ns= 16.8c T: 5.12ns= 21.50c
XCHG r8, [m8] L: 4.01ns= 16.8c T: 5.12ns= 21.50c
XCHG r16, [m16] L: 4.01ns= 16.8c T: 5.12ns= 21.50c
XCHG r32, [m32] L: 4.01ns= 16.8c T: 5.20ns= 21.83c
XCHG r64, [m64] L: 4.01ns= 16.8c T: 5.12ns= 21.50c
ADD r32, 0x04000 L: 0.33ns= 1.0c T: 0.12ns= 0.36c
ADD r32, 0x08000 L: 0.31ns= 0.9c T: 0.12ns= 0.37c
ADD r32, 0x10000 L: 0.31ns= 0.9c T: 0.12ns= 0.36c
ADD r32, 0x20000 L: 0.31ns= 0.9c T: 0.12ns= 0.36c
ADD r8, r8 L: 0.31ns= 0.9c T: 0.11ns= 0.34c
ADD r16, r16 L: 0.31ns= 0.9c T: 0.11ns= 0.32c
ADD r32, r32 L: 0.31ns= 0.9c T: 0.11ns= 0.34c
ADD r64, r64 L: 0.31ns= 0.9c T: 0.10ns= 0.31c
ADD r8, [m8] L: 1.87ns= 5.6c T: 0.16ns= 0.47c
ADD r16, [m16] L: 1.87ns= 5.6c T: 0.16ns= 0.47c
ADD r32, [m32] L: 1.87ns= 5.6c T: 0.16ns= 0.47c
ADD r64, [m64] L: 1.87ns= 5.6c T: 0.16ns= 0.47c
ADD [m8], r8 L: 1.89ns= 5.7c T: 0.33ns= 1.00c
ADD [m16], r16 L: 1.87ns= 5.6c T: 0.26ns= 0.78c
ADD [m32], r32 L: 1.87ns= 5.6c T: 0.28ns= 0.84c
ADD [m32 + 8], r32 L: 1.89ns= 5.7c T: 0.26ns= 0.78c
ADD [m64], r64 L: 1.89ns= 5.7c T: 0.33ns= 1.00c
ADD [m64 + 16], r64 L: 1.89ns= 5.7c T: 0.24ns= 0.73c
我一直在尝试在 NOP 方面对 CAS 和 DCAS 进行基准测试。
我有一些结果,但我还不相信它们 - 验证正在进行中。
目前,我在 Core i5 上看到了 CAS/DCAS 3/5 NOP。在 Xeon 上,我看到 20/22。
这些结果可能完全不正确 - 您已被警告。