什么时候CPU可以忽略LOCK前缀并使用缓存一致性?

use*_*112 6 cpu concurrency x86 multithreading caching

我原本认为缓存一致性协议(如MESI)可以提供伪原子性,仅限于单个内存加载/存储指令.如果我正在执行获取,修改,写入指令组合,单独的MESI将无法在第一条指令到最后一条指令中强制执行原子性.

但是,英特尔参考手册第3a卷第8节说:

8.1.4 LOCK操作对内部处理器高速缓存的影响

对于P6和更新的处理器系列,如果在LOCK操作期间被锁定的存储器区域被高速缓存在执行LOCK操作作为回写存储器并且完全包含在高速缓存行中的处理器中,则处理器可能不会断言总线上的LOCK#信号.相反,它将在内部修改内存位置并允许其缓存一致性机制,以确保以原子方式执行操作.此操作称为"缓存锁定".缓存一致性机制自动防止缓存相同内存区域的两个或多个处理器同时修改该区域中的数据.

http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.pdf

这似乎与我的理解相矛盾,暗示LOCK指令不需要使用,因为可以使用缓存一致性?

Lee*_*eor 5

作为概念的锁定与实际的总线 #lock 信号之间存在差异 - 后者是实现第一个的方法之一。缓存锁定是另一种更简单、更有效的锁定。

MESI 协议保证,如果某条线路由某个核心独占(无论是否修改),其他人都没有。在这种情况下,您可以通过在缓存中添加简单的标志来自动执行多个操作,该标志会阻止外部窥探直到操作完成。这将具有与锁概念所规定的相同效果,因为没有其他人可能会更改甚至观察中间值。

在更复杂的情况下,该行不由单个缓存保存(例如,它可能在多个缓存之间共享,或者访问可能在两个缓存行之间拆分并且只有一个在您的缓存中 - 场景列表通常是实现具体的,可能没有由 CPU 制造商披露) - 在这种情况下,您可能不得不求助于“更重”的大炮,如总线锁,这通常保证没有人可以在共享总线上做任何事情。显然这对性能有巨大的影响,所以这可能只在你别无选择的情况下使用。在大多数情况下,一个简单的缓存级锁就足够了。请注意,像 Intel TSX 这样的新方案似乎以类似的方式工作,当您在缓存中工作时提供优化。

顺便说一句-您对单个指令的伪原子性的假设也是错误的-如果您提到单个内存操作(加载或存储),那将是正确的,因为一条指令可能包含多个指令(inc [addr]例如,如果没有一把锁)。您的报价中也出现的另一个限制是访问需要包含在缓存行中 - 即使在单个加载或存储中,拆分行也不能保证原子性(因为它们通常被实现为 2 个内存操作,这些操作后来合并)。