0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

CPU缓存一致性协议解析

strongerHuang 来源:strongerHuang 2023-07-12 10:07 次阅读

CPU运行效率高不高,一定程度取决于缓存,这里就给大家分享一下CPU缓存相关的内容。

CPU高速缓存(Cache Memory)

CPU为何要有高速缓存

CPU在摩尔定律的指导下以每18个月翻一番的速度在发展,然而内存和硬盘的发展速度远远不及CPU。这就造成了高性能能的内存和硬盘价格及其昂贵。然而CPU的高度运算需要高速的数据。为了解决这个问题,CPU厂商在CPU中内置了少量的高速缓存以解决IO速度和CPU运算速度之间的不匹配问题。 在CPU访问存储设备时,无论是存取数据抑或存取指令,都趋于聚集在一片连续的区域中,这就被称为局部性原理。

时间局部性(Temporal Locality):如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。

比如循环、递归、方法的反复调用等。

空间局部性(Spatial Locality):如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。

比如顺序执行的代码、连续创建的两个对象、数组等。

带有高速缓存的CPU执行计算的流程

程序以及数据被加载到主内存

指令和数据被加载到CPU的高速缓存

CPU执行指令,把结果写到高速缓存

高速缓存中的数据写回主内存

26196f78-1fec-11ee-962d-dac502259ad0.png

目前流行的多级缓存结构

由于CPU的运算速度超越了1级缓存的数据IO能力,CPU厂商又引入了多级的缓存结构。

多级缓存结构


263030be-1fec-11ee-962d-dac502259ad0.png

多核CPU多级缓存一致性协议MESI

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

MESI协议缓存状态

MESI 是指4中状态的首字母。每个Cache line有4个状态,可用2个bit表示,它们分别是:

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

状态 描述 监听任务

M 修改 (Modified) 该Cache line有效,数据被修改了,和内存中的数据不一致,数据只存在于本Cache中。 缓存行必须时刻监听所有试图读该缓存行相对就主存的操作,这种操作必须在缓存将该缓存行写回主存并将状态变成S(共享)状态之前被延迟执行。
E 独享、互斥 (Exclusive) 该Cache line有效,数据和内存中的数据一致,数据只存在于本Cache中。 缓存行也必须监听其它缓存读主存中该缓存行的操作,一旦有这种操作,该缓存行需要变成S(共享)状态。
S 共享 (Shared) 该Cache line有效,数据和内存中的数据一致,数据存在于很多Cache中。 缓存行也必须监听其它缓存使该缓存行无效或者独享该缓存行的请求,并将该缓存行变成无效(Invalid)。
I 无效 (Invalid) 该Cache line无效。

注意: 对于M和E状态而言总是精确的,他们在和该缓存行的真正状态是一致的,而S状态可能是非一致的。如果一个缓存将处于S状态的缓存行作废了,而另一个缓存实际上可能已经独享了该缓存行,但是该缓存却不会将该缓存行升迁为E状态,这是因为其它缓存不会广播他们作废掉该缓存行的通知,同样由于缓存并没有保存该缓存行的copy的数量,因此(即使有这种通知)也没有办法确定自己是否已经独享了该缓存行。 从上面的意义看来E状态是一种投机性的优化:如果一个CPU想修改一个处于S状态的缓存行,总线事务需要将所有该缓存行的copy变成invalid状态,而修改E状态的缓存不需要使用总线事务。

MESI状态转换

264ae85a-1fec-11ee-962d-dac502259ad0.png


理解该图的前置说明: 1.触发事件 触发事件 描述

本地读取(Local read 本地cache读取本地cache数据
本地写入(Local write) 本地cache写入本地cache数据
远端读取(Remote read) 其他cache读取本地cache数据
远端写入(Remote write) 其他cache写入本地cache数据

2.cache分类: 前提:所有的cache共同缓存了主内存中的某一条数据。 本地cache:指当前cpu的cache。 触发cache:触发读写事件的cache。 其他cache:指既除了以上两种之外的cache。 注意:本地的事件触发 本地cache和触发cache为相同。 上图的切换解释: 状态 触发本地读取 触发本地写入 触发远端读取 触发远端写入

M状态(修改) 本地cache:M 触发cache:M 其他cache:I 本地cache:M 触发cache:M 其他cache:I 本地cache:M→E→S 触发cache:I→S 其他cache:I→S 同步主内存后修改为E独享,同步触发、其他cache后本地、触发、其他cache修改为S共享 本地cache:M→E→S→I 触发cache:I→S→E→M 其他cache:I→S→I 同步和读取一样,同步完成后触发cache改为M,本地、其他cache改为I
E状态(独享) 本地cache:E 触发cache:E 其他cache:I 本地cache:E→M 触发cache:E→M 其他cache:I 本地cache变更为M,其他cache状态应当是I(无效) 本地cache:E→S 触发cache:I→S 其他cache:I→S 当其他cache要读取该数据时,其他、触发、本地cache都被设置为S(共享) 本地cache:E→S→I 触发cache:I→S→E→M 其他cache:I→S→I 当触发cache修改本地cache独享数据时时,将本地、触发、其他cache修改为S共享.然后触发cache修改为独享,其他、本地cache修改为I(无效),触发cache再修改为M
S状态(共享) 本地cache:S 触发cache:S 其他cache:S 本地cache:S→E→M 触发cache:S→E→M 其他cache:S→I 当本地cache修改时,将本地cache修改为E,其他cache修改为I,然后再将本地cache为M状态 本地cache:S 触发cache:S 其他cache:S 本地cache:S→I 触发cache:S→E→M 其他cache:S→I 当触发cache要修改本地共享数据时,触发cache修改为E(独享),本地、其他cache修改为I(无效),触发cache再次修改为M(修改)
I状态(无效) 本地cache:I→S或者I→E 触发cache:I→S或者I →E 其他cache:E、M、I→S、I 本地、触发cache将从I无效修改为S共享或者E独享,其他cache将从E、M、I 变为S或者I 本地cache:I→S→E→M 触发cache:I→S→E→M 其他cache:M、E、S→S→I 既然是本cache是I,其他cache操作与它无关 既然是本cache是I,其他cache操作与它无关

下图示意了,当一个cache line的调整的状态的时候,另外一个cache line 需要调整的状态。 M E S I

M × × ×
E × × ×
S × ×
I

举个栗子来说: 假设cache 1 中有一个变量x = 0的cache line 处于S状态(共享)。 那么其他拥有x变量的cache 2、cache 3等x的cache line调整为S状态(共享)或者调整为 I 状态(无效)。

多核缓存协同操作

假设有三个CPU A、B、C,对应三个缓存分别是cache a、b、 c。在主内存中定义了x的引用值为0。 26b24720-1fec-11ee-962d-dac502259ad0.png

单核读取

那么执行流程是: CPU A发出了一条指令,从主内存中读取x。 从主内存通过bus读取到缓存中(远端读取Remote read),这是该Cache line修改为E状态(独享). 26d92d54-1fec-11ee-962d-dac502259ad0.png

双核读取

那么执行流程是: CPU A发出了一条指令,从主内存中读取x。 CPU A从主内存通过bus读取到 cache a中并将该cache line 设置为E状态。 CPU B发出了一条指令,从主内存中读取x。 CPU B试图从主内存中读取x时,CPU A检测到了地址冲突。这时CPU A对相关数据做出响应。此时x 存储于cache a和cache b中,x在chche a和cache b中都被设置为S状态(共享)。


26f86b7e-1fec-11ee-962d-dac502259ad0.png

修改数据

那么执行流程是: CPU A 计算完成后发指令需要修改x. CPU A 将x设置为M状态(修改)并通知缓存了x的CPU B, CPU B将本地cache b中的x设置为I状态(无效) CPU A 对x进行赋值。 271de944-1fec-11ee-962d-dac502259ad0.png

同步数据

那么执行流程是: CPU B 发出了要读取x的指令。 CPU B 通知CPU A,CPU A将修改后的数据同步到主内存时cache a 修改为E(独享) CPU A同步CPU B的x,将cache a和同步后cache b中的x设置为S状态(共享)。 273b826a-1fec-11ee-962d-dac502259ad0.png

MESI优化和他们引入的问题

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

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

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

Store Bufferes

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

Store Bufferes的风险

第一、就是处理器会尝试从存储缓存(Store buffer)中读取值,但它还没有进行提交。这个的解决方案称为Store Forwarding,它使得加载的时候,如果存储缓存中存在,则进行返回。 第二、保存什么时候会完成,这个并没有任何保证。


value = 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;
}

现在确实安全了。完美无暇!

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10816

    浏览量

    210978
  • 存储
    +关注

    关注

    13

    文章

    4245

    浏览量

    85623
  • 内存
    +关注

    关注

    8

    文章

    2991

    浏览量

    73843
  • 缓存
    +关注

    关注

    1

    文章

    231

    浏览量

    26640

原文标题:CPU缓存一致性协议

文章出处:【微信号:strongerHuang,微信公众号:strongerHuang】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何解决数据库与缓存一致性

    缓存一致性 每次逢年过节的时候抢票非常艰难,放票的时候那么多人同时去抢票,如果所有人查询、购票等都去访问数据库,那数据库的压力得有多大,这时候很多都会引入缓存, 把车票信息放入缓存,这
    的头像 发表于 09-25 15:25 1037次阅读
    如何解决数据库与<b class='flag-5'>缓存</b><b class='flag-5'>一致性</b>

    小编科普CPU缓存一致性协议MESI

    什么是缓存一致性协议MESI?MESI协议中的状态有哪几种?MESI协议中的状态是如何相互转换的?
    发表于 06-17 10:00

    请教大神在Arm AMBA协议集中,什么叫缓存一致性

    请教大神在Arm AMBA协议集中,什么叫缓存一致性
    发表于 09-29 14:51

    改进的基于目录的Cache一致性协议

    介绍几种典型目录一致性协议并分析它们的优缺点。在综合全映射目录和有限目录优点的基础上,通过在存储器层上增加个存储器高速缓存(Cache)层的方式,提出并讨论
    发表于 04-02 09:05 32次下载

    CMP中Cache一致性协议的验证

    CMP是处理器体系结构发展的个重要方向,其中Cache一致性问题的验证是CMP设计中的项重要课题。基于MESI一致性协议,本文建立了CM
    发表于 07-20 14:18 38次下载

    RFID协议一致性测试系统设计(二)

      软件无线电这关键技术的应用,使得RFID协议一致性测试系统能够突破传统仪器受专有硬件限制的局限性,在标准化、模块化、层次化的体系结构上满足一致性测试的需求。RFID
    发表于 03-28 17:37 1428次阅读
    RFID<b class='flag-5'>协议</b><b class='flag-5'>一致性</b>测试系统设计(二)

    RFID协议一致性测试系统设计(三)

      在具体实现了RFID协议一致性测试系统之后,我们将可以应用于对RFID单元的实际测试之中,本节以EPC UHF Class 1 Gen 2(也被称为ISO 18000-6 Type C)标准的协议
    发表于 03-28 17:37 1278次阅读
    RFID<b class='flag-5'>协议</b><b class='flag-5'>一致性</b>测试系统设计(三)

    加速器一致性接口

    提供异步缓存一致性直接访问PS的入口。处理器可以标记ACP上的传输为一致性或非一致性。PL端的AXI主机通过ARUSERS[1:0]指示是否为一致性
    发表于 11-17 15:04 3578次阅读

    Cache一致性协议优化研究

    问题的由来.总结了多核时代高速缓存一致性协议设计的关键问题,综述了近年来学术界对一致性的研究.从程序访存行为模式、目录组织结构、一致性粒度、
    发表于 12-30 15:04 0次下载
    Cache<b class='flag-5'>一致性</b><b class='flag-5'>协议</b>优化研究

    自主驾驶系统将使用缓存一致性互连IP和非一致性互连IP

    代ASIL B(D)自主驾驶系统将使用符合ISO 26262标准的缓存一致性互连IP和非一致性互连IP来实现。 美国加利福尼亚州坎贝尔2019年4月26日消息—Arteris IP
    的头像 发表于 05-09 17:13 3187次阅读

    管理基于Cortex®-M7的MCU的高速缓存一致性

    本文档概述了不同场景下的高速缓存一致性问题,并就如何管理或避免高速缓存一致性问题提供了些方法建议。
    发表于 04-01 10:12 5次下载
    管理基于Cortex®-M7的MCU的高速<b class='flag-5'>缓存</b><b class='flag-5'>一致性</b>

    介绍下cpu缓存一致性(MESI协议

    之前介绍了java并发包的cas原理和java内存模型,这篇我们介绍下cpu缓存一致性原理,可以帮助我们更好的理解cas的底层原理。
    的头像 发表于 06-09 16:01 4543次阅读
    介绍下<b class='flag-5'>cpu</b><b class='flag-5'>缓存</b><b class='flag-5'>一致性</b>(MESI<b class='flag-5'>协议</b>)

    如何保证缓存一致性

    “ 本文的参考文章是2022年HOT 34上Intel Rob Blakenship关于CXL缓存一致性篇介绍。”
    的头像 发表于 10-19 17:42 1022次阅读
    如何保证<b class='flag-5'>缓存</b><b class='flag-5'>一致性</b>

    Redis缓存与Mysql如何保证一致性

    基本流程就是客户端A请求,先去删除缓存,然后将数据写入数据库,此时客户端B查询先去查询缓存缓存没有返回,去查数据库,此时还没有完成主从同步,拿到是从库的旧数据,然后将旧数据进行缓存
    的头像 发表于 12-02 14:23 880次阅读
    Redis<b class='flag-5'>缓存</b>与Mysql如何保证<b class='flag-5'>一致性</b>?

    异构计算下缓存一致性的重要

    在众多回复中,李博杰同学的回答被认为质量最高。他首先将缓存一致性分为两个主要场景:是主机内CPU与设备间的一致性;二是跨主机的
    的头像 发表于 10-24 17:00 246次阅读
    异构计算下<b class='flag-5'>缓存</b><b class='flag-5'>一致性</b>的重要<b class='flag-5'>性</b>