侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

一篇文章让你明白CPU缓存一致性协议MESI

2022-07-14 星期四 / 0 评论 / 0 点赞 / 33 阅读 / 6194 字

CPU高速缓存(Cache Memory)CPU为何要有高速缓存CPU在摩尔定律的指导下以每18个月翻一番的速度在发展,然而内存和硬盘的发展速度远远不及CPU。这就造成了高性能能的内存和硬盘价格及其昂

CPU高速缓存(Cache Memory)

.

CPU为何要有高速缓存

...CPU在摩尔定律的指导下以每18个月翻一番的速度在发展,然而内存和硬盘的发展速度远远不及CPU。这就造成了高性能能的内存和硬盘价格及其昂贵。然而CPU的高度运算需要高速的数据。为了解决这个问题,CPU厂商在CPU中内置了少量的高速缓存以解决I/O速度和CPU运算速度之间的不匹配问题。....在CPU访问存储设备时,无论是存取数据抑或存取指令,都趋于聚集在一片连续的区域中,这就被称为局部性原理。....时间局部性(Temporal Locality):如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。比如循环、递归、方法的反复调用等。....空间局部性(Spatial Locality):如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。比如顺序执行的代码、连续创建的两个对象、数组等。..............
..

MESI优化和他们引入的问题

..缓存的一致性消息传递是要时间的,这就使其切换时会产生延迟。当一个缓存被切换状态时其他缓存收到消息完成各自的切换并且发出回应消息这么一长串的时间中CPU都会等待所有缓存响应完成。可能出现的阻塞都会导致各种各样的性能问题和稳定性问题。..


.

CPU切换状态阻塞解决-存储缓存(Store Bufferes)

...比如你需要修改本地缓存中的一条信息,那么你必须将I(无效)状态通知到其他拥有该缓存数据的CPU缓存中,并且等待确认。等待确认的过程会阻塞处理器,这会降低处理器的性能。应为这个等待远远比一个指令的执行时间长的多。..


.

Store Bufferes

...为了避免这种CPU运算能力的浪费,Store Bufferes被引入使用。处理器把它想要写入到主存的值写到缓存,然后继续去处理其他事情。当所有失效确认(Invalidate Acknowledge)都接收到时,数据才会最终被提交。....这么做有两个风险..


.

Store Bufferes的风险

...第一、就是处理器会尝试从存储缓存(Store buffer)中读取值,但它还没有进行提交。这个的解决方案称为Store Forwarding,它使得加载的时候,如果存储缓存中存在,则进行返回。....第二、保存什么时候会完成,这个并没有任何保证。..
alue = 3;void exeToCPUA(){  value = 10;  isFinsh = true;}void exeToCPUB(){  if(isFinsh){    //value一定等于10?!    assert value == 10;  }}
..试想一下开始执行时,CPU A保存着finished在E(独享)状态,而value并没有保存在它的缓存中。(例如,Invalid)。在这种情况下,value会比finished更迟地抛弃存储缓存。完全有可能CPU B读取finished的值为true,而value的值不等于10。....即isFinsh的赋值在value赋值之前。....这种在可识别的行为中发生的变化称为重排序(reordings)。注意,这不意味着你的指令的位置被恶意(或者好意)地更改。....它只是意味着其他的CPU会读到跟程序中写入的顺序不一样的结果。....顺便提一下NIO的设计和Store Bufferes的设计是非常相像的。..


.

硬件内存模型

...执行失效也不是一个简单的操作,它需要处理器去处理。另外,存储缓存(Store Buffers)并不是无穷大的,所以处理器有时需要等待失效确认的返回。这两个操作都会使得性能大幅降低。为了应付这种情况,引入了失效队列。它们的约定如下:..
  • .对于所有的收到的Invalidate请求,Invalidate Acknowlege消息必须立刻发送.
  • .Invalidate并不真正执行,而是被放在一个特殊的队列中,在方便的时候才会去执行。.
  • .处理器不会发送任何消息给所处理的缓存条目,直到它处理Invalidate。.
..即便是这样处理器已然不知道什么时候优化是允许的,而什么时候并不允许。....干脆处理器将这个任务丢给了写代码的人。这就是内存屏障(Memory Barriers)。..............
....写屏障 Store Memory Barrier(a.k.a. ST, SMB, smp_wmb)是一条告诉处理器在执行这之后的指令之前,应用所有已经在存储缓存(store buffer)中的保存的指令。....读屏障Load Memory Barrier (a.k.a. LD, RMB, smp_rmb)是一条告诉处理器在执行任何的加载前,先应用所有已经在失效队列中的失效操作的指令。..
void executedOnCpu0() {    value = 10;    //在更新数据之前必须将所有存储缓存(store buffer)中的指令执行完毕。    storeMemoryBarrier();    finished = true;}void executedOnCpu1() {    while(!finished);    //在读取之前将所有失效队列中关于该数据的指令执行完毕。    loadMemoryBarrier();    assert value == 10;}
..
..

最后

..欢迎大家关注我的公种浩【程序员追风】,整理了1000道2019年多家公司java面试题400多页pdf文档,文章都会在里面更新,整理的资料也会放在里面。喜欢文章记得点个赞,感谢支持!..


.
.

广告 广告

评论区