竹笋

首页 » 问答 » 环境 » 多核CPU多级缓存一致性协议MESI
TUhjnbcbe - 2023/6/24 20:52:00
北京看荨麻疹的好医院 http://pf.39.net/bdfyy/bdfhl/210719/9204186.html

多核CPU的情况下有多个一级缓存,如何保证缓存内部数据的一致,不让系统数据混乱。这里就引出了一个一致性的协议MESI。

MESI协议缓存状态

MESI是指缓存行的4种状态的首字母。每个Cacheline有4个状态,可用2个bit表示,它们分别是:

缓存行(Cacheline):缓存存储数据的单元。

M修改(Modified):该缓存行有效,数据被修改了,和内存中的数据不一致,数据只存在于本缓存行中。

E独享、互斥(Exclusive):该缓存行有效,数据和内存中的数据一致,数据只存在于本缓存行中。

S共享(Shared):该缓存行有效,数据和内存中的数据一致,数据存在于很多缓存行中。

I无效(Invalid):该缓存行无效。

对于M和E状态而言总是精确的,他们在和该缓存行的真正状态是一致的,而S状态可能是非一致的。如果一个缓存将处于S状态的缓存行作废了,而另一个缓存实际上可能已经独享了该缓存行,但是该缓存却不会将该缓存行升迁为E状态,这是因为其它缓存不会广播他们作废掉该缓存行的通知,同样由于缓存并没有保存该缓存行的copy的数量,因此(即使有这种通知)也没有办法确定自己是否已经独享了该缓存行。

从上面的意义看来E状态是一种投机性的优化:如果一个CPU想修改一个处于S状态的缓存行,总线事务需要将所有该缓存行的copy变成invalid状态,而修改E状态的缓存不需要使用总线事务。

缓存行伪共享

CPU缓存系统中是以缓存行(cacheline)为单位存储的。目前主流的CPUCache的CacheLine大小都是64Bytes。在多线程情况下,如果需要修改“共享同一个缓存行的变量”,就会无意中影响彼此的性能,这就是伪共享(FalseSharing)。

举个例子:现在有2个long型变量a、b,如果有线程t1在访问a,线程t2在访问b,而a与b刚好在同一个cacheline中,此时t1先修改a,将导致b被刷新!

MESI优化和他们引入的问题

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

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

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

StoreBufferes

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

这么做有两个风险,StoreBufferes的风险。

第一、就是处理器会尝试从存储缓存(Storebuffer)中读取值,但它还没有进行提交。这个的解决方案称为StoreForwarding,它使得加载的时候,如果存储缓存中存在,则进行返回。

第二、保存什么时候会完成,这个并没有任何保证。

1
查看完整版本: 多核CPU多级缓存一致性协议MESI