Multithreading Intel CPU上atomics cmpxchg指令的平均延迟

Multithreading Intel CPU上atomics cmpxchg指令的平均延迟,multithreading,x86,atomic,lock-free,Multithreading,X86,Atomic,Lock Free,我正在寻找一些关于各种英特尔处理器的lock cmpxchg指令平均延迟的参考资料。我找不到关于这个主题的任何好的参考资料,任何参考资料都会有很大帮助 谢谢。关于这方面的参考文献很少,如果有的话,因为变化太多了。它基本上取决于一切,包括总线速度、内存速度、处理器速度、处理器计数、周围指令、内存围栏,很可能还有月球和珠穆朗玛峰之间的角度 如果您有一个非常特定的应用程序,如已知(固定)硬件、操作环境、实时操作系统和独占控制,那么它可能会很重要。在本例中,使用基准测试。如果您对软件运行的位置没有这种级


我正在寻找一些关于各种英特尔处理器的lock cmpxchg指令平均延迟的参考资料。我找不到关于这个主题的任何好的参考资料,任何参考资料都会有很大帮助


谢谢。

关于这方面的参考文献很少,如果有的话,因为变化太多了。它基本上取决于一切,包括总线速度、内存速度、处理器速度、处理器计数、周围指令、内存围栏,很可能还有月球和珠穆朗玛峰之间的角度

如果您有一个非常特定的应用程序,如已知(固定)硬件、操作环境、实时操作系统和独占控制,那么它可能会很重要。在本例中,使用基准测试。如果您对软件运行的位置没有这种级别的控制,那么任何度量实际上都是毫无意义的

正如中所讨论的,锁是使用CAS实现的,因此,如果您可以使用CAS而不是锁(至少需要两个操作),那么它会更快(很明显?只是可能)


你能找到的最好的参考资料是,虽然有太多的变化,他们不会给你一个实际的数字。然而,他们将描述如何获得尽可能最好的性能。可能一份处理器数据表(如i7极限版的数据表,在“技术文档”下)会给出实际的数字(或至少是一个范围)。

我一直在尝试用NOP对CAS和DCA进行基准测试

我有一些结果,但我还不相信他们-验证正在进行中

目前,我在核心i5上看到了CAS/DCAS 3/5 NOP。在Xeon上,我看到20/22


这些结果可能完全不正确-您已收到警告。

根据对各种Intel/AMD/VIA芯片的实际经验测量,最好的x86指令延迟参考可能包含在中,并经常针对市场上最新的CPU进行更新

不幸的是,我没有看到指令延迟表中列出的
CMPXCHG
指令,但第4页确实说明:

带有锁前缀的指令具有很长的延迟,这取决于缓存组织和RAM速度。如果有多个处理器或内核或直接内存访问(DMA)设备,则所有锁定的指令将锁定缓存线以进行独占访问,这可能涉及RAM访问。即使在单处理器系统上,锁前缀通常也要花费100多个时钟周期。这也适用于带有内存操作数的XCHG指令


几个月来,我一直在研究指数退避


CAS的延迟完全取决于指令是否可以从缓存操作或必须从内存操作。通常,给定的内存地址由多个线程(例如,指向队列的入口指针)确定。如果最近成功的CAS是由与当前CAS执行器共享缓存的逻辑处理器执行的(L1、L2或L3,当然更高级别的执行器速度较慢),则该指令将在缓存上运行,并且速度很快—只有几个周期。如果最新成功的CAS是由不与当前执行器共享缓存的逻辑核执行的,则最新CASer的写入将使当前执行器的缓存线无效,并且需要进行内存读取-这将需要数百个周期


CAS操作本身非常快(只有几个周期),问题在于内存。

您可以使用AIDA64软件检查指令延迟(但您无法检查要检查的指令,它有一个硬编码的指令列表)。人们正在网上公布结果

lock
指令中,AIDA64验证
lock add
指令和
xchg[mem]
(即使没有明确的锁
前缀,也始终锁定)

这里有一些信息。我还将为您提供以下说明的延迟,以供比较:

  • xchg reg1、reg2
    未锁定
  • 添加到寄存器和内存中
如您所见,Haswell DT上的锁定指令仅比非锁定内存存储慢5倍,而Kaby Lake-S上的锁定指令仅比非锁定内存存储慢2倍

英特尔Core i5-4430,3000 MHz(30 x 100)Haswell DT 英特尔Core i7-7700K,4700 MHz(47 x 100)卡比湖-S
可以将其视为对主存的读+写。OTOH,可能是Ulrich Drepper的“每个程序员都应该知道的内存”有更多的细节。除了病态的好奇心,你在做什么需要知道平均延迟?@MSN:不太超过病态的好奇心…我在做研究:-)。。。基本上要弄清楚具有细粒度同步的应用程序是否有机会在多核上运行,如果有,什么时候……感谢Zooba,这很有帮助。我查看了数据表,但可以找到cmpxchg类型说明的参考。我问这个问题的原因是,这个操作在core-i3上执行得很好,在Xeon上执行得很糟糕……我不知道为什么会出现这种情况……因此我在寻找一些参考资料……指令“lock cmpxchg”是x86.FWIW上的CAS,并非所有锁都需要两个
CAS
操作。x86上的许多锁是通过获取路径上的
CAS
xchg
实现的,但在解锁路径上有一个简单的存储。x86内存模型足够强大,可以正常工作。请注意,这些值是在核心一级缓存中使用的数据。CAS表示比较和交换?DCAS表示双重比较和服务,NOP表示?CAS是单字CAS。DCAS是连续的双字CAS。NOP是无操作说明。谢谢,你能分享一个关于你提到的CAS的链接吗。我发现有些是比较和交换的,有些是比较和设置的……CAS是一个通用的缩写词。例如,英特尔称之为“比较和交换”——我认为这已经过时了。我记得我曾经做过这样的测试。我记得从Intel Core Duo pr开始
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