对互斥锁的 unlock/lock 操作如何比从内存中获取更快?

How can an unlock/lock operation on a mutex be faster than a fetch from memory?

Norvig 声称,互斥锁定或解锁操作只需要从内存中获取所需时间的四分之一。

这个 answer 解释说,互斥量是 本质上是一个标志和一个等待队列,只需要几条指令就可以在无竞争的互斥锁上翻转标志。

  1. 我假设,如果不同的 CPU 或核心试图锁定该互斥体,它需要等待 要写回内存的缓存行(如果尚未发生)和读取其自己的内存以获取标志的状态。那是对的吗?有什么区别,如果是不同的核心相比不同的CPU?

  2. 所以 Norvig 状态的数字仅适用于 CPU 或尝试操作的核心在其缓存中已经具有该标志并且缓存行不脏的无竞争互斥体?

典型的 PC 运行 x86 CPU,英特尔的 CPU 可以完全在缓存上执行锁定:

if the area of memory being locked during a LOCK operation is cached in the processor that is performing the LOCK operation as write-back memory and is completely contained in a cache line, the processor may not assert the LOCK# signal on the bus.
Instead, it will modify the memory location internally and allow it’s cache coherency mechanism to ensure that the operation is carried out atomically.
This operation is called “cache locking.”
The cache coherency mechanism automatically prevents two or more processors that have cached the same area of memory from simultaneously modifying data in that area.

From Intel Software Developer Manual 3, Section 8.1.4

缓存一致性机制是 MESI 协议的变体。
在这样的协议中,CPU 可以写入缓存位置之前,它必须具有处于独占 (E) 状态的相应行。
这意味着一次只有一个 CPU 的给定内存位置处于脏状态。
当其他 CPU 想要读取同一位置时,所有者 CPU 将延迟此类读取,直到原子操作完成。
然后它遵循一致性协议转发、无效或回写该行。

在上述情况下,执行锁定的速度可能比未缓存加载的速度快。

然而,那些时代有点过时了,肯定已经过时了。
它们的目的是在典型操作中给出一个 顺序 ,以及一个数量级。
L1命中的时间有点奇怪,它并不比典型的指令执行快(它本身不能用一个数字来描述)。
Intel 优化手册报告,对于像 Sandy Bridge 这样的旧 CPU,L1 访问时间为 4 个周期,而有很多指令的延迟为 4 个周期以下。

我会对这些数字持保留态度,避免对它们进行过多推理。
Norvig试图教给我们的教训是:硬件是分层的,越靠近(从拓扑的角度1)到CPU,速度越快。
所以在解析文件时,程序员应该避免在文件中来回移动数据,而是应该尽量减少IO压力。
some在处理数组时适用,locality会提高性能。
但是请注意,这些在技术上是 micro-optimisations and the topic is not as simple as it appears


1 大体上把硬件分为:内核内部(寄存器),CPU内部(缓存,可能不是LLC),套接字(GPU,LLC),在专用总线设备(内存,其他 CPUs)之后,在一个通用总线(PCIe - 网卡等内部设备)之后,在两个或更多总线(USB 设备,磁盘)之后,并且在完全是另一台计算机(服务器)。