繁体   English   中英

为什么CompareAndSwap指令被认为是昂贵的?

[英]Why is CompareAndSwap instruction considered expensive?

为什么CompareAndSwap指令被认为是昂贵的?

我读了一本书:

“内存障碍很昂贵,与原子compareAndSet()指令一样昂贵。”

谢谢!

“CAS与正常商店的区别并不明显。有关CAS的一些错误信息可能源于英特尔处理器上最初的lock:cmpxchg(CAS)实现.lock:前缀导致LOCK#信号被置位,获得独占权访问总线。这当然没有扩展。随后的锁实现:cmpxchg利用缓存一致性协议 - 通常是基于snoop的MESI - 并且不会断言LOCK#。 - David Dice, HotSpot中的偏向锁定

“内存障碍很昂贵,与原子compareAndSet()指令一样昂贵。”

这是真的。
例如,在x86上,多处理器系统上的正确CAS具有锁定前缀。
锁定前缀会导致完整的内存屏障:

“...锁定操作序列化所有未完成的加载和存储操作(即等待它们完成)。” ......“锁定操作相对于所有其他内存操作和所有外部可见事件都是原子操作。只有指令获取和页表访问才能传递锁定指令。锁定指令可用于同步由一个处理器写入的数据并由另一个处理器读取“。 - 英特尔®64和IA-32架构软件开发人员手册 ,第8.1.2章。

事实上LOCK AND在x86 / x64上的.NETJAVA JIT中 ,内存屏障实现为虚拟LOCK ORLOCK AND
在x86上,CAS会产生完整的内存屏障。

在PPC上,它是不同的。 LL / SC对 - lwarxstwcx - 可用于将内存操作数加载到寄存器中,然后在目标位置没有其他存储时将其写回,或者如果存在则重试整个循环。 LL / SC可以被中断。
它也不意味着自动全栅栏。
不同体系结构的性能特征和行为可能会有很大差异。
但话说回来 - 弱LL / SC不是CAS。

那是因为它们为操作原子引入了额外的开销。 底层平台必须抑制优化(如缓存)并暂停线程执行以促进障碍,这需要大量额外的工作。 当额外的活动正在进行时,线程无法执行,因此整个程序会产生时间延迟。

“昂贵”在这里非常相对。 与硬盘访问相比,这绝对是微不足道的。 但是RAM总线速度跟不上现代CPU的速度,并且与CPU内部的算术运算相比,直接访问RAM(即非缓存)非常昂贵。 从RAM中获取int可以轻松地花费50倍的时间而不是添加两个寄存器。

因此,由于内存屏障基本上强制直接RAM访问(可能用于多个CPU),因此它们相对昂贵。

我想我在书中找到了答案:

每个getAndSet()都广播到总线。 因为所有线程都必须使用总线与内存通信,这些getAndSet()调用会延迟所有线程(核心),甚至是那些不等待锁定的线程。

更糟糕的是,getAndSet()调用强制其他处理器丢弃它们自己的锁缓存副本,因此每个旋转线程几乎每次都会遇到缓存未命中,并且必须使用总线来获取新的但未更改的值。

通常,原子操作很昂贵,因为它们需要跨CPU同步。 允许“正常”操作对缓存数据进行操作,从而允许额外的速度。 例如,在2个CPU系统上:

线程1

while (1) x++;

线程2

while (1) x++;

因为增量不是原子操作或受内存屏障保护,所以结果几乎没有定义。 你不知道x将如何递增,或者它甚至可能被破坏。

线程1

while (1) atomicIncrement(&x);

线程2

while (1) atomicIncrement(&x);

现在,您正在尝试获得良好定义的行为 - 无论顺序如何,x必须逐个增加。 如果两个线程在不同的CPU上运行,则它们必须减少允许的缓存量或以其他方式“比较注释”以确保发生合理的事情。

这种额外的开销可能非常昂贵,并且这是声称原子操作很慢的一般原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM