小林图解系统-二.硬件结构 2.4CPU缓存一致性

CPU Cache的数据写入

CPU和内存的访问性能越差越大,于是在CPU内部嵌入CPU Cache(高速缓存)。

CPU Cache由Cache Line组成,Cache Line由头标志Tag+数据块Data Block组成。

如果数据写入Cache,内存和Cache相对应的数据将不同,需要同步,什么时机才把Cache中的数据写回到内存呢?

两种针对写入数据的方法:写直达(Write Through),写回(Write Back)

写直达

保存内存与Cache一致性最简单的方式,把数据同时写入内存和Cache中

写入前会先判断是否已经在CPU Cache里面:

如果数据已经在Cache里面,先将数据更新到Cache里面,再写入到内存里面;

如果数据没有在Cache里面,就直接把数据更新到内存里面。

写回

既然写直达由于每次操作都会把数据写回内存,导致影响性能,为了减少数据写回内存的频率,出现了写回方法。

当发生写操作时,新的数据仅仅被写入到Cache Block里,只有当修改过的Cache Block[被替换过]才需要写到内存里,减少了数据写回内存的频率,提高性能。

  • 当发生写操作时,数据已经在CPU Cache里的话,把数据更新到CPU Cache里,标记CPU Cache里的这个Cache Block为(Dirty)的,代表这个时候,CPU Cache里面的Cache Block的数据和内存是不一致的,这种情况不用把数据写到内存里;
  • 当发生写操作时,数据所对应的Cache Block里存放的是[别的内存地址的数据]的话,检查这个Cache Block里的数据有没有被标记为脏的:

        如果是脏的,把这个Cache Block里的数据写回到内存,然后再把当前要写入的数据,先从内存读到Cache Block,然后把要写入的数据写入到Cache Block,最后也标记为脏的。

        如果不是脏的,把当前要写入的数据先从内存读入到Cache Block,接着将数据写入到这个Cache Block里,再把这个Cache Block标记为脏的。

写回这个方法,把数据写入到Cache的时候,只有在缓存不命中同时数据对应的Cache中的Cache Block为脏标记的情况下,才会将数据写到内存中。而在缓存命中情况下,只需要把该数据对应的Cache Block标记为脏即可。

好处是,如果大量操作可以命中缓存,大部分时间里的CPU都不需要写入内存,性能就会提升。

为什么缓存没命中,还要定位Cache Block?此时要判断数据即将写入到Cache Blcok 里的位置,是否被[其他数据]占了此位置,如果这个[其他数据]是脏数据,就要帮忙把它写回到内存


缓存一致性问题

 L1/L2 Cache是多个核心各自独有的,就会带来多核心的缓存一致性(Cache Coherence)的问题。

A  B两个核心,A执行i++语句,为了考虑性能使用写回策略,先把值为1的执行结果写入到L1 L2Cache,然后把L1/L2 Cache标记为脏的,这时候其实没有被同步到内存,因为只有Cache Block要被替换的时候,数据才会写入到内存里。

如果此时B核心尝试从内存读取i的值,则是错误的,因为A号核心更新i值还没写入到内存,内存中的值依然是0。这个就是所谓的缓存一致性问题,A号核心和B号核心的缓存,在这个时候是不一致的,从而会导致执行结果的错误。

同步:

第一:某个CPU核心的Cache数据更新时,必须传播到其他核心的Cache,称为写传播(Write Propagation)

第二:某个CPU核心里对数据的操作顺序,必须在其他核心看起来顺序是一样的,称为事务的串行化(Transaction Serialization),要做到两点:CPU核心对于Cache中数据的操作需要同步给其他核心;要引入锁概念,如果两个CPU核心里有相同数据的Cache,那么对于这个Cache数据的更新,只有拿到了锁,才能进行对应的数据更新。


总线嗅探

写传播:当某个CPU核心更新了Cache中的数据,要把该时间广播通知到其他核心。最常见实现方式是总线嗅探(Bus Snooping)

A号CPU核心修改了L1 Cache中i变量的值,通过总线把这个时间广播通知给其他所有核心,然后每个CPU核心都会监听总线上的广播事件,并检查是否有相同的数据在自己的L1 Cache里面,如果B号CPU核心的L1Cache中有该数据,那么也需要把该数据更新到自己的L1 Cache。

总线嗅探不管别的核心的Cache是否缓存相同的数据,都需要发出一个广播事件,加重总线负载。

另外,总线嗅探只是保证了某个CPU核心的Cache会更新数据这个事件被其他知道,但不能保证事务串行化

于是,有一个协议基于总线嗅探机制实现了事务串行化,也用状态机机制降低了总线带宽压力,这个协议就是MESI协议,这个协议就做到了CPU缓存一致性。


MESI协议

Modified,已修改

Exclusive,独占

Shared,共享

Invalidated,已失效

这个状态来标记Cache Line四个不同状态。

[已修改]状态是脏标记,代表该Cache Block上的数据已经被更新过,但是还没有写到内存里。而[已失效]状态,表示的是这个Cache Block里的数据已经失效了,不可以读取该状态的数据。

[独占][共享]状态代表Cache Block里的数据是干净的,也就是说,这个时候Cache Block里的数据和内存里面的数据是一致性的。

差别在于,独占,数据只存储在一个CPU核心的Cache里,而其他CPU河西你的Cache没有该数据。如果向独占Cache写数据,就可以直接自由地写入,不需要通知其他CPU核心,因为只有你有这个数据,不存在缓存一致性。

独占下的数据,如果有其他核心从内存读取了相同的数据到各自的Cache,这个时候,独占状态下的数据就会变成共享状态。

那么,[共享]状态代表着相同的数据在多个CPU核心的Cache里都有,所以当我们要更新Cache里面的数据的时候,不能直接更改,需要向其他CPU核心广播一个请求,要求先把其他核心的Cache中对应的Cache Line标记为[无效]状态,然后再更新当前Cache里面的数据。

所以当Cache Line状态是[已修改]和[独占]状态时修改更新其数据不需要发送广播给其他CPU核心,这在一定程度上减少了总线带宽压力


总结

CPU 在读写数据的时候,都是在 CPU Cache 读写数据的,原因是 Cache 离 CPU 很近,读写性能相比内存高出很多。对于 Cache 里没有缓存 CPU 所需要读取的数据的这种情况,CPU 则会从内存读取数据,并将数据缓存到 Cache 里面,最后 CPU 再从 Cache 读取数据。

而对于数据的写入,CPU 都会先写入到 Cache 里面,然后再在找个合适的时机写入到内存,那就有「写直达」和「写回」这两种策略来保证 Cache 与内存的数据一致性:

  • 写直达,只要有数据写入,都会直接把数据写入到内存里面,这种方式简单直观,但是性能就会受限于内存的访问速度;
  • 写回,对于已经缓存在 Cache 的数据的写入,只需要更新其数据就可以,不用写入到内存,只有在需要把缓存里面的脏数据交换出去的时候,才把数据同步到内存里,这种方式在缓存命中率高的情况,性能会更好;

当今 CPU 都是多核的,每个核心都有各自独立的 L1/L2 Cache,只有 L3 Cache 是多个核心之间共享的。所以,我们要确保多核缓存是一致性的,否则会出现错误的结果。

要想实现缓存一致性,关键是要满足 2 点:

  • 第一点是写传播,也就是当某个 CPU 核心发生写入操作时,需要把该事件广播通知给其他核心;
  • 第二点是事物的串行化,这个很重要,只有保证了这个,才能保障我们的数据是真正一致的,我们的程序在各个不同的核心上运行的结果也是一致的;

基于总线嗅探机制的 MESI 协议,就满足上面了这两点,因此它是保障缓存一致性的协议。

MESI 协议,是已修改、独占、共享、已失效这四个状态的英文缩写的组合。整个 MSI 状态的变更,则是根据来自本地 CPU 核心的请求,或者来自其他 CPU 核心通过总线传输过来的请求,从而构成一个流动的状态机。另外,对于在「已修改」或者「独占」状态的 Cache Line,修改更新其数据不需要发送广播给其他 CPU 核心。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/30524.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis-五种数据结构之列表(ziplist、quicklist)

列表 文章目录 列表压缩列表-ziplistziplist 定义级联更新 快速列表-quicklistquicklistNode 定义quicklist 定义quicklist常用操作其他操作quicklist 相对于普通链表优点quick应用场景在redis 中使用quicklist 列表数据类型可以存储一组按插入顺序排序的字符串,他很…

昇思大模型学习·第一天

mindspore快速入门回顾 导入mindspore包 处理数据集 下载mnist数据集进行数据集预处理 MnistDataset()方法train_dataset.get_col_names() 打印列名信息使用create_tuple_iterator 或create_dict_iterator对数据集进行迭代访问 网络构建 mindspore.nn: 构建所有网络的基类用…

Linux搭建Minio单机环境

😊 作者: 一恍过去 💖 主页: https://blog.csdn.net/zhuocailing3390 🎊 社区: Java技术栈交流 🎉 主题: Linux搭建Minio单机环境 ⏱️ 创作时间: 2024年06月19日 目…

Linux网络命令:网络速度测试工具 speedtest-cli 详解

目录 一、概述 二、安装 speedtest-cli 1、在基于 Debian 的系统上安装 2、在基于 Red Hat 的系统上安装 三、命令语法 1、基本命令语法 2、查看帮助 3、常用选项 四、 speedtest-cli使用示例 1. 基本测试 2. 列出所有可用的服务器 3. 指定服务器进行测试 …

C语言—数据在内存中的存储

1.整数在内存中的存储 文章回顾(C语言—操作符详解) 整数的2进制表示方式有三种,即原码、反码和补码。 有符号的整数,三种表示方式均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”&…

数据库 | 试卷四

1.数据库系统的特点是 数据共享、减少数据冗余、数据独立、避免了数据不一致和加强了数据保护 2.关系模型的数据结构是二维表结构 3.聚簇索引 cluster index 4. 这里B,C都是主属性,所以B->C不是非主属性对码的部分函数依赖 候选键(AC&a…

LabVIEW共享变量

共享变量简介 LabVIEW​为​创建​分布​式​应用使用​共享​变量​可以简化​此类​应用的编程。​ 借助​共享​变量,​您​可以​在​同​一个​程序​框​图​的​不同​循环​之间​或者网络上​的​不同VI之间​共享​数据。与LabVIEW中的许多​其他数据​共…

htb_Editorial

hack the book Editorial 端口扫描 80 22 目录扫描 /upload 是一个上传book information的页面 其中最顶上有一个可以上传书本封面的地方,可以从本地上传,也可以从远程下载 这里可能涉及ssrf和本地文件上传,逐一尝试 随便上传一个图片…

idea搜索只显示100条、如何修改idea搜索的条数

文章目录 一、老版本的IDEA(2021年之前的版本)二、新版本的IDEA(2021年及之后的版本)2.1、方式一2.2、方式二 如下图:idea搜索的时候默认只显示100条 要解决IDEA搜索只显示100条的问题,可以通过修改搜索结…

【UML用户指南】-19-对基本行为建模-用例图

目录 1、组成结构 2、表示法 3、一般用法 3.1、对主题的语境建模 3.2、对主题的需求建模 4、常用建模技术 4.1、对系统的语境建模 4.1.1、设计过程 4.2、对系统的需求建模 4.2.1、设计过程: 5、正向工程 UML 中的用例图是对系统的动态方面建模的 5 种图之…

进入docker容器内部操作mysql数据库

文章目录 1、查询docker容器2、进入mysql容器内部3、连接mysql数据库4、查询mysql所有的数据库5、使用某个数据库6、展示数据库中所有的表7、查询某张表8、断开mysql9、退出mysql容器 1、查询docker容器 [rootlocalhost ~]# docker ps CONTAINER ID IMAGE …

商城小程序:颠覆传统电商,打造全新商业生态

在数字化浪潮的推动下,网购行业呈现多元化繁荣发展态势,出现了琳琅满目的商品应用小程序,但市面上的商城小程序基本属于通用型,无论是商城界面展示和基本功能,都不能满足个性化和商品推广需求,阻碍了商品的…

Building wheels for collected packages: mmcv, mmcv-full 卡住

安装 anime-face-detector 的时候遇到一个问题:Installation takes forever #1386:在构建mmcv-full时卡住,这里分享下解决方法(安装 mmcv 同理,将下面命令中的 mmcv-full 替换成 mmcv) 具体表现如下&#x…

基于Java技术的家乡特色推荐系统

开头语:你好呀,我是计算机学姐码农小野!如果有相关需求,可以私信联系我。 开发语言:Java 数据库:MySQL 技术:Java技术,SpringBoot框架 工具:Eclipse,Navi…

强大的多数据库客户端工具:DataGrip【送源码】

今天给大家带来的工具是:DataGrip 介绍 DataGrip是jetbrains开发的一款关系数据库和 NoSQL 数据库的多数据库客户端工具,可以30天免费试用,后续使用需要购买。 DataGrip还是一款强大的跨平台工具,支持多种操作系统,比…

英伟达市值飙升,超越苹果微软并超过英国股市总市值

原标题:英伟达超越苹果微软市值,成为全球市值最高的企业 易采游戏网6月19日消息:近日,美国科技巨头英伟达市值的迅速增长引起了市场广泛关注。据最新数据显示,截至本周二收盘,英伟达的市场资本化已达到3.34…

基于Redis提高查询性能(保持数据一致性)

Redis实战篇 | Kyles Blog (cyborg2077.github.io) 目录 背景 商户查询缓存(根据ID查询) 根据店铺类型查询(List型) 缓存更新策略(保证数据一致性) 案例(利用缓存更新策略) 背景 起初客户端…

【pytorch01】简单回归问题

1.梯度下降(Gradient Descent) y x 2 ∗ s i n ( x ) yx^{2}*sin(x) yx2∗sin(x) y ′ 2 ∗ x ∗ s i n ( x ) x 2 ∗ c o s ( x ) y2*x*sin(x) x^{2}*cos(x) y′2∗x∗sin(x)x2∗cos(x) 求最小值要求导 梯度下降定义:梯度下降要迭代计…

【决战欧洲杯巅峰】AI模型预测[走地数据]初步准备工作

数据准备 首先,我们需要收集一些与欧洲杯比赛相关的历史数据。这些数据可能包括球队的历史战绩、球员的能力评分、比赛场地信息、历史交锋记录等。这些数据可以从公开来源获取,并进行适当的预处理和清洗。 特征提取 接下来,我们需要从收集…

vue3+ts+vite集成eslint

项目中安装eslint yarn add eslint -Deslint初始化 npx eslint --init按照下方操作即可 安装typescript-eslint/parser yarn add typescript-eslint/parser -D安装vite-plugin-eslint2 yarn add vite-plugin-eslint2 -D配置vite-plugin-eslint2 // vite.config.ts import …