multithreading - 缓存一致性在多核和多处理器架构中如何工作?

标签 multithreading caching mesi

让我解释一下我的理解,并请您确认其正确性或纠正我:

  1. 有一个 MESI 协议(protocol),可以实现高效的缓存一致性 ( https://en.wikipedia.org/wiki/MESI_protocol )。这是最先进的机制。
  2. 对于单个处理器的多个内核,MESI 通过在处理器内核之间共享的 L3 缓存进行操作。
  3. 对于多个处理器(没有共享 L3),MESI 通过主内存运行。
  4. 当使用由多个线程读写的全局变量时, volatile 类型说明符用于防止不必要的优化以及防止在寄存器中进行缓存(<强>不在 L1-3 缓存中)。因此,如果值不在寄存器中,而是在缓存或主内存中,MESI 将尽力使线程看到全局变量的正确值。

最佳答案

For several cores of a single processor, MESI operates via L3 cache which is shared among cores of a processor.

MESI 在所有缓存级别上运行。在某些处理器设计中,L3 缓存充当内核之间的高效“交换机”。例如,如果 L3 高速缓存是包容性的,并且保存任何 CPU 的 L1 或 L2 高速缓存中的所有内容,那么只需知道某些内容不在 L3 高速缓存中就足以知道它不在任何其他核心的高速缓存中。这可以减少所需的窥探量。不过,这些都是复杂的优化。

For several processors (with no shared L3), MESI operates via Main Memory.

我不确定你想在这里说什么,但它似乎与事实不符。 MESI 在缓存之间运行。内存不是缓存,因此不需要参与 MESI 协议(protocol)。

您的意思可能是,对于没有 L3 缓存的 CPU,L2 缓存间 MESI 流量发生在与连接到主内存的 CPU 总线相同的 CPU 总线上。在 CPU 具有片上内存 Controller 之前,某些多芯片 CPU 设计就是如此。但如今,大多数笔记本电脑/台式机多核 CPU 都带有芯片内存 Controller ,因此连接到内存的总线仅连接到内存。所以那里没有 MESI 流量。如果数据位于一个核心的二级缓存中并且必须到达另一个核心的二级缓存,则它不会越过内存。 (想想内核和内存 Controller 的拓扑,这太疯狂了。)

When using global variables, which are read and written by several threads, volatile type specifier is used to prevent unwanted optimizations as well as to prevent caching in registers (not in L1-3 caches).

据我所知,没有一种语言是这样的。在 C/C++ 中当然不是这样,其中 volatile 用于信号之类的东西而不是多线程(至少在具有明确定义的多线程 API 的平台上)。对于像 Java 这样的东西来说,情况并非如此,其中 volatile 具有与寄存器无关的特定语言语义。

Thus, if value is not in a register but in cache or main memory, MESI would do its work to make threads see correct values of globals.

这在硬件/汇编器级别可能是正确的。这就是寄存器存在的地方。但实际上,这并不是因为虽然 MESI 使内存缓存保持一致,但现代 CPU 还进行了其他优化,从而产生了相同类型的问题。例如,CPU 可能会预取读取或可能延迟无序写入。所以除了 MESI 之外,你还需要内存屏障之类的东西。当然,这非常特定于平台。

您可以将 MESI 视为一种优化。为了使线程间内存可见性正常工作,您仍然必须执行平台要求的任何操作。但 MESI 极大地减少了这项工作。

例如,如果没有 MESI,您可能会采用一种设计,其中数据从一个内核传输到另一个内核的唯一方法是通过写入主内存,然后等待写入完成,然后从主内存读取。那将是一场彻底的灾难。首先,您最终必须将内容刷新到主内存,以防另一个线程需要它。其次,所有这些流量都会阻塞常规内存流量。恶心。

关于multithreading - 缓存一致性在多核和多处理器架构中如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35511686/

相关文章:

c++ - memory_order_seq_cst 栅栏什么时候有用?

c++ - 在一个线程上删除具有数百万个字符串的大型 HashMap 会影响另一个线程的性能

android - 在 Android 中使用 Looper.prepare() 的细节

algorithm - 提出加权算法的因素?

caching - MESI 协议(protocol)中的 L3$ 角色部分是什么

caching - 为什么MESI协议(protocol)需要Exclusive状态

android - onCreate() 中的新处理程序

java - 根据服务名称和参数缓存 Hessian 服务结果

javascript - 如何在用户的浏览器中缓存我的网站?

multithreading - LOCK 前缀与 MESI 协议(protocol)?