1 CPU高速缓存

1.1 cpu为什么要有告诉缓存

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

多线程第三节_mesi_缓存

多线程第三节_mesi_高速缓存_02

2 MESI

2.1 多核cpu多级缓存一致性协议MESI

多核CPU的情况下有多个一级缓存,如何保证缓存内部数据的一致,不让系统数据混乱。这里就引出了一个 一致性的协议MESI。
MESI协议缓存状态
MESI是指四种状态的首字母。每个cache line 有四个状态他们分别是M(修改) E(独享,互斥) S(共享) I(无效)
注意: 对于M和E状态而言总是精确的,他们在和该缓存行的真正状态是一致的,而S状态可能是非一致的。如果 一个缓存将处于S状态的缓存行作废了,而另一个缓存实际上可能已经独享了该缓存行,但是该缓存却不会 将该缓存行升迁为E状态,这是因为其它缓存不会广播他们作废掉该缓存行的通知,同样由于缓存并没有保 存该缓存行的copy的数量,因此(即使有这种通知)也没有办法确定自己是否已经独享了该缓存行。 从上面的意义看来E状态是一种投机性的优化:如果一个CPU想修改一个处于S状态的缓存行,总线事务需 要将所有该缓存行的copy变成invalid状态,而修改E状态的缓存不需要使用总线事务。

多线程第三节_mesi_高速缓存_03

多线程第三节_mesi_缓存_04

2.2 cpu切换状态阻塞解决-存储缓存(Store bufferes)

缓存的一致性消息传递是要时间,这就使其切换时会产生延迟,当一个缓存被切换状态时,其他缓存受到消息完成各自的切换并且发出回应消息这么一长串时间中cpu都会等待所有缓存完成响应。可能会出现阻塞导致各种性能和稳定性问题。
cpu切换状态阻塞解决-存储缓存
当你需要修改本地缓存中的一条信息,必须将 I(无效)状态通知到其他拥有该缓存数据的cpu缓存中,并且等待确认,这个过程会被阻塞处理,但是时间会特别长。所以引入存储缓存
store bufferes(存储缓存)
处理器把它想要写入到贮存的值写到缓存,然后去处理其他事情。当所有失效确认都介绍到,数据才会最终被提交,这么做会有俩个风险
1. 处理器会尝试从存储缓存中读取值,但他还没来的及进行提交。这个解决方案叫store forwarding,它使得加载的时候,如果有存储缓存存在,就进行返回。
2. 保存什么时候完成,这个并没有保存
3. 硬件内存模型,执行失效不是一个简单的操作,他需要处理器处理,另外存储缓存并不是无穷大,所有处理器有时需要等待失效确认的返回,这俩个操作使得性能大幅度降低,为了应付这种情况。引入了失效队列,约定如下:
1 对于所有收到invalidate请求,invalidate acknowlege 必须立刻发送
2 invalidate并不会真正立刻执行,而是放到一个特殊队列,在方便的时候才会执行
3 处理器不会发送任何消息给所处理的缓存条目,知道它处理invalidate。即使时这样子处理器依然不知道什么时候优化是被允许的,所以处理器讲这个任务丢给了写代码的人,也就是内存屏障

多线程第三节_mesi_缓存_05


不会,我可以学;落后,我可以追赶;跌倒,我可以站起来!