CPU缓存一致性问题

今天复习了下CPU缓存的知识。(๑•̀ㅂ•́)و✧

文章目录

    • 数据写入内存的两种方式
    • 缓存一致性问题
    • 总线嗅探
    • MESI协议
    • 伪共享

CPU的访问速率要远高于内存的访问速率,为了减少内存访问次数,提高计算机系统效率,CPU中引入了缓存。

在这里插入图片描述
这是我虚拟机的三级缓存结构。L1d和L1i是一级缓存,他距离cpu核心最近,
其中,l1d用来存数据,l1i用来存指令。L1和L1 cache是每个核心独有的缓存,而L3则是多个cpu核心共享的。
缓存每次从内存中读取的数据的大小cache line 可以从这里看到,默认是64字节。
在这里插入图片描述
接下来进入正题:

数据写入内存的两种方式

如何同步cache和内存的数据呢?
写直达 & 写回
写直达就是每次写数据的时候都同时往cache和内存写。如果写操作比较频繁的话,这样显然效率很低。
写回则是cpu只往cache写,只有当某个cache block要被替换时,才把他写回内存,这就引出了下一个问题:

缓存一致性问题

因为每个cpu核心都有自己私有的cache。假设有两个cpu核心A和B,他们都从内存读取了同一个变量i,之后A修改了 i 的值并且写回了内存,此时B的缓存中 i 的值就和内存中的i不一样了。

  • 为了保证数据的一致性,首先要做到 写传播,即一个cpu修改了cache数据时,要通知给其他的cpu。
  • 其次要做到 事务串行化,假设有两个个cpu核心,都修改了同一个变量 i,他们俩在把“我修改了 i ”这个消息传递给其他cpu时,可能消息达到的顺序不同,这样也会产生问题。

总线嗅探

通过总线嗅探可以实现写传播,但是会增加总线的压力,另外,总线嗅探也不能保证事务串行化。

MESI协议

MESI协议解决了写传播事务串行化这两个问题。
MESI用四种状态来表示cache的状态:

  • M:Modified 修改
  • E:Exclusive 独占
  • S:Shared 共享
  • I:Invalidated 失效

MESI协议中,如果有个cpu核心修改了cache的值,他就会把自己这个cache block标志为M,同时告诉其他的核心,让他们把对应的cache block标记为I,如果qita核心要读取这块内容的话,他就要先把这个cache block写回内存,然后状态该改为S。
还有其他几种情况,比如要写的时候发现是 I。用MESI的四种状态都可以解决。

伪共享

但这里还有一个不太合理的地方,假设cpu核心A和B都读取了相同的cache block,A一直修改缓存中 a的值,B则一直修改 b的值。按理说他们俩操作不同的值应该是不存在一致性问题的,但由于a和b这俩变量挨得比较近,会读取到同一个cache block中,A每次修改完a就会把B的cache block置为无效,B也一样,这就是伪共享问题。

缓存-伪共享问题

你可能感兴趣的:(开发语言,linux)