存储器 - 缓存一致性 MESI 协议:如何让多核CPU的高速缓存保持一致
存储器 - 缓存一致性 MESI 协议:如何让多核CPU的高速缓存保持一致
计算机组成原理目录:https://www.cnblogs.com/binarylei/p/12585607.html
在上一篇 存储器 - 高速缓存(CPU Cache):为什么要使用高速缓存 中,我们分析了高速缓存(CPU Cache) 的数据结构,及如何进行读写操作。在写操作时,可以通过使用写回策略替换直接写策略,将数据先写到 CPU Cache 中,从而提高吞吐率。但始终还遗留了一个问题,那就是多核 CPU 如何保证 Cache 的一致性?
1. 缓存一致性
1.1 问题根源
- CPU Cache:解决的是内存访问速度和 CPU 的速度差距太大的问题。
- 多核 CPU:在主频难以提升的时候,通过增加 CPU 个数来提升 CPU 的吞吐率的办法。
我们把多核和 CPU Cache 两者一结合,就给我们带来了一个新的挑战。因为 CPU 的每个核各有各的缓存,互相之间的操作又是各自独立的,就会带来缓存一致性(Cache Coherence) 的问题。
如上图所示 CPU Cache 中,L1 和 L2 Cache 都是 CPU 独有的,而 L3 和 DRAM 则是共有的。如果 CPU-1 更新了自己的 L1 或 L2 Cache 没有更新主存,或者 CPU-1 写的同时 CPU-2 并发读,则会造成 CPU-1 和 CPU-2 的数据不一致。无论是直接写还是写回策略都没有解决这个问题。
1.2 解决方案
为了解决这个缓存不一致的问题,我们就需要有一种机制,来同步两个不同 CPU 的缓存数据。那这样的机制需要满足什么条件呢?我觉得能够做到下面两点就是合理的。
-
写传播(Write Propagation):在一个 CPU 核心里,我们的 Cache 数据更新,必须能够传播到其他的对应节点的 Cache Line 里。
-
事务的串行化(Transaction Serialization):在一个 CPU 核心里面的读取和写入,在其他的节点看起来,顺序是一样的。
事务的串行化比较难理解,举个例子。有 CPU-1~4 四个 CPU,CPU-1 将数据 i 修改成 5000,而 CPU-2 将数据 i 修改成 6000,它们都将修改的操作广播给其余两个 CPU。CPU-3 可能先收到 CPU-1 的广播,将 i 修改成 5000,而接着又收到 CPU-2 的广播,将 i 修改成 6000,而 CPU-4 恰好相反,先修改成 6000 再修改成 5000。这样就造成这两个 CPU 数据的不一致,也就是没做到事务的串行化。
2. 总线嗅探机制和 MESI 协议
要解决缓存一致性问题,首先要解决的是多个 CPU 之间的数据传播问题。
- 总线嗅探(Bus Snooping):最常见的一种解决多核 CPU 数据广播问题的方案。本质上就是把所有的读写请求都通过总线(Bus) 广播给所有的 CPU 核心,然后让各个核心去“嗅探”这些请求,再根据本地的情况进行响应。
- MESI 协议:基于总线嗅探机制的缓存一致性协议,MESI 协议也是在 Pentium 时代被引入到 Intel CPU。
2.1 写传播 vs 写失效
- 写失效(Write Invalidate) 协议:在写失效协议里,在这个 CPU 写入 Cache 后,它会去广播一个“失效”请求给其他所有 CPU。其他 CPU 如果也存在这个缓存行,直接标记成失效的就好了。MESI 协议使用的就是写失效协议。
- 写传播(Write Invalidate) 协议:会将数据广播给其他 CPU,相对于写失效请求,占用更多的带宽。
2.2 MESI 协议
MESI 协议的由来呢,来自于我们对 Cache Line 的四个不同的标记,分别是:
- M:代表已修改(Modified),表示数据修改后未同步到主存的脏数据。
- E:代表独占(Exclusive),独占模式下,可以对应数据任意修改,不需要广播给其它 CPU。
- S:代表共享(Shared),当有两个 CPU 读取数据时,缓存行的状态从独占变成共享。此时修改数据时,需要广播给其他 CPU。
- I:代表已失效(Invalidated),表示数据已经失效,需要重新从主存中读取数据。
参考:
- 《大话计算机》 6.9 章节:比较详细地讲解了多核 CPU 的访问存储数据的一致性问题。
每天用心记录一点点。内容也许不重要,但习惯很重要!
posted on 2020-03-29 08:01 binarylei 阅读(1880) 评论(0) 编辑 收藏 举报