小林Coding阅读笔记:操作系统篇之硬件结构,CPU Cache一致性问题

news2024/11/24 16:19:24

前言

  1. 参考/导流:
    小林coding-2.4 CPU 缓存一致性
  2. 学习意义
  • 底层基础知识,了解CPU执行过程,让上层编码有效
  • 并发控制底层设计思维(对比 MySQL的并发控制)、更好地去理解JUC的锁、volatile以及JMM
  • 架构层面的一致性保证问题,由CPU协调单位上升至线程、进程、机器
  1. 相关说明
    该篇博文是个人阅读的重要梳理,仅做简单参考,详细请阅读小林coding的原文!

四、CPU缓存一致性

CPU Cache 和 内存不一致性

程序先加载至内存中,CPU执行程序需要先读取缓存Cache,若无该数据(内存地址)则读取内存。而计算机中使用 数据 是使用它的信息,可以存在不同地方,一份数据可存在于 Cache和内存,对于来说,未改变信息的状态【只需保证写的一致性,则读就会一致】,无论它在Cache,还是内存,它们是一致性的。而对于来说,则会改变数据的状态,此时则会导致 Cache的数据是新数据,内存由于距离远而是旧数据。此时,则产生了 缓存 和 内存 不一致的问题。对于CPU的缓存和内存不一致性的解决办法有:

  • 写直达:当缓存更新数据之后,直接写到内存,随时保证缓存和内存的一致性。问题则是加大了写的开销。如果单核情况下,CPU读数据优先从Cache读,本来该数据缓存已有该数据,无需从内存加载,随时保证缓存和内存一致性的必要性也不大。因此,只需考虑当Cache被替换,不再命中时,需要再从内存拿数据时,才更新cache的数据至内存即可。那么对于多核呢?多核则是后续Cache间来保证一致性的讨论。
  • 写回:在写直达的基础,写回则是当CacheBlock被替换,需要再从内存拿数据时才去更新至内存【而cacheblock被替换时也不一定是被更改过的,此时则需要去标记该数据是否为脏,若脏则需要写回内存】。这样就会减少由Cache写至内存的频率。增大效率。

Cache的读写策略

写直达

保持内存与 Cache 一致性最简单的方式是,把数据同时写入内存和 Cache 中,这种方法称为写直达(Write Through

在这里插入图片描述

写回

直达由于每次写操作都会把数据写回到内存,而导致影响性能,于是为了要减少数据写回内存的频率,就出现了写回(Write Back)的方法

在写回机制中,当发生写操作时,新的数据仅仅被写入 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写命中(Write Hit)时的策略

  • 写直达 (Write Through)
    CPU向Cache写数据时,Memory中的内容也将被同步更新。

    好处是可以保证Cache和Memory的一致性,坏处是影响运行速度。【对比CAP理论,程序设计总是 性能和可用之间做平衡】

  • 写回(Write Back)
    CPU向Cache写数据时,Memory中的内容将不立刻做同步更新,只做Dirty标记。当Cache块被换出时,才将改动同步到Memory中。

    好处是保证了程序运行速度,坏处是存在Cache和Memory的不一致性。

Cache写缺失(Write Miss)时的策略
写失效(write miss)即所要写的地址不在cache中。

  • Write allocate
    把要写的数据载入到Cache中,写Cache,然后再通过flush方式写入到内存中
  • No write allocate
    直接把要写的数据写入到内存中。

Cache读策略

  • Read through
    直接从内存中读取数据
  • Read allocate
    先把数据读取到Cache中,再从Cache中读数据。

多核心的缓存间不一致性

问题引入

现在 CPU 都是多核的,由于 L1/L2 Cache 是多个核心各自独有的,那么会带来多核心的缓存一致性(Cache Coherence 的问题,如果不能保证缓存一致性的问题,就可能造成结果错误。【对比 分布式架构,由核心 上升至 机器;内部通信 由 总线,到 网络通信】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G5UseOB6-1671416925411)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/9f148b27-7234-44c3-b2db-4f9439f0ac69/Untitled.png)]

这时如果 A 号核心执行了 i++ 语句的时候,为了考虑性能,使用了我们前面所说的**写回策略【**若采用写直达,时刻保证内存的数据最新,是否也会存在该问题?因为在写至内存之前,另外的核心也可能去读内存?也需要锁去保证 顺序性】,先把值为 1 的执行结果写入到 L1/L2 Cache 中,然后把 L1/L2 Cache 中对应的 Block 标记为脏的,这个时候数据其实没有被同步到内存中的,因为写回策略,只有在 A 号核心中的这个 Cache Block 要被替换的时候,数据才会写入到内存里。

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

解决以上问题,则需要保证以下两点:

  • 写传播,当一个核心更新数据,能通知到其他核心。【手段方式,对比RPC中的心跳检测机制,】
  • 串行化,保证事务的串行化,让核心执行事务是顺序性的。【目标,手段通过锁—】

要实现事务串行化,要做到 2 点:

  • CPU 核心对于 Cache 中数据的操作,需要同步给其他 CPU 核心;
  • 要引入「」的概念,如果两个 CPU 核心里有相同数据的 Cache,那么对于这个 Cache 数据的更新,只有拿到了「锁」,才能进行对应的数据更新。

具体实现

  • 总线嗅探【类似心跳检测,rpc发消息通知,结合着 分布式事务\RPC通信对比】
  • MESI协议【对比共识算法、数据一致性算法以及MySQL的ACID特性】

总线嗅探

写传播的原则就是当某个 CPU 核心更新了 Cache 中的数据,要把该事件广播通知到其他核心【时刻监听广播事件】。最常见实现的方式是总线嗅探(Bus Snooping)。

  • 广播
  • 监听

问题点:

  • CPU 需要每时每刻监听总线上的一切活动,但是不管别的核心的 Cache 是否缓存相同的数据,都需要发出一个广播事件。
  • 总线嗅探只是保证了某个 CPU 核心的 Cache 更新数据这个事件能被其他 CPU 核心知道,但是并不能保证事务串行化。

MESI协议

在总线嗅探时讨论,对于发广播事件的CPU核心无论别的核心是否用该数据都发生,对于其他CPU核心需要时刻监听广播通知。针对该两种问题,可以去细粒度标记数据 Cacheline的状态,来减少不必要的开销浪费。

MESI则通过以下四个状态来标记 Cache Line 四个不同的状态,来更好地进行广播传播,保证同步以及 实现 串行化。

  • Modified,已修改
  • Exclusive,独占
  • Shared,共享
  • Invalidated,已失效

已修改状态,代表该 Cache Block 上的数据已经被更新过(脏标记),但没有写到内存里。

已失效状态,表示的是这个 Cache Block 里的数据已经失效了,不可以读取该状态的数据。

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

「独占」和「共享」的差别在于,独占状态的时候,数据只存储在一个 CPU 核心的 Cache 里,而其他 CPU 核心的 Cache 没有该数据。这个时候,如果要向独占的 Cache 写数据,就可以直接自由地写入,而不需要通知其他 CPU 核心,因为只有你这有这个数据,就不存在缓存一致性的问题了,于是就可以随便操作该数据。

状态转换

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XwiE7751-1671416946964)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/990ffa50-8582-4158-a0f6-6ce62122fbf7/Untitled.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X3hKyULp-1671416925412)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/5c97cb7d-a392-40ca-bdb5-34aa36e14f9f/Untitled.png)]

具体示例

  1. 当 A 号 CPU 核心从内存读取变量 i 的值,数据被缓存在 A 号 CPU 核心自己的 Cache 里面,此时其他 CPU 核心的 Cache 没有缓存该数据,于是标记 Cache Line 状态为「独占」,此时其 Cache 中的数据与内存是一致的;
  2. 然后 B 号 CPU 核心也从内存读取了变量 i 的值,此时会发送消息给其他 CPU 核心,由于 A 号 CPU 核心已经缓存了该数据,所以会把数据返回给 B 号 CPU 核心。在这个时候, A 和 B 核心缓存了相同的数据,Cache Line 的状态就会变成「共享」,并且其 Cache 中的数据与内存也是一致的;
  3. 当 A 号 CPU 核心要修改 Cache 中 i 变量的值,发现数据对应的 Cache Line 的状态是共享状态,则要向所有的其他 CPU 核心广播一个请求,要求先把其他核心的 Cache 中对应的 Cache Line 标记为「无效」状态,然后 A 号 CPU 核心才更新 Cache 里面的数据,同时标记 Cache Line 为「已修改」状态,此时 Cache 中的数据就与内存不一致了。
  4. 如果 A 号 CPU 核心「继续」修改 Cache 中 i 变量的值,由于此时的 Cache Line 是「已修改」状态,因此不需要给其他 CPU 核心发送消息,直接更新数据即可。
  5. 如果 A 号 CPU 核心的 Cache 里的 i 变量对应的 Cache Line 要被「替换」,发现 Cache Line 状态是「已修改」状态,就会在替换前先把数据同步到内存。

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

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

相关文章

毕业设计 单片机便携式空气质量检测仪 - 物联网 嵌入式

文章目录0 前言1 简介2 主要器件3 实现效果4 设计原理5 部分核心代码5 最后0 前言 🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长…

51.`.format`字符串格式化—最适合小白的格式化笔记

51..format字符串格式化 文章目录51..format字符串格式化1.课题导入2.知识回顾3..format的基本用法3.1{}为空3.2 {}中有编号3.3 {}中有变量名4.浮点数的格式化5..format官方语法6. .format格式化语法总结7. 总结8.课堂练习1.课题导入 【描述】 用input函数输入你每个月的工资…

MySQL中WHERE后跟着N多个OR条件会怎样...

GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。作者:叶金荣文章来源:社区原创 可能会执行非常慢,线上生产环境千万别写出这种SQL ... 背景交…

Docker+Gitlab+Jenkins+Springboot

安装Gitlab 开放防火墙端口80和配置映射文件夹 firewall-cmd --zonepublic --add-port80/tcp --permanent firewall-cmd --reload mkdir -p /docker_data/gitlab/{data,logs,config}启动Gitlab容器(启动容器之前确保80,443端口没用被占用,被…

H3C双点双向路由引入,以及使用路由策略进行路由控制,路由学习的配置

如下拓扑中,存在两个路由域,左边为isis区域,所有设备均为level-1-2角色。右边为ospf区域,所有使能ospf的接口均在area0区域中: 组网中需要在R1和R3上,分别将各自的isis路由引入到ospf进程中,同时…

Go C 编程 第9课 放飞汽球(魔法学院的奇幻之旅 Go C编程绘图)

Goc编程第八课 Goc编程第八课_哔哩哔哩_bilibili Goc编程第九课 Goc编程第九课_哔哩哔哩_bilibili 59.实心椭圆 (魔法学院第9课) 难度:1 登录 60.双色椭圆 (魔法学院第9课) 难度:1 登录 61.气球串 (魔法学院第9课) 登录 62.同心圆环 (魔法学院第9课…

C++类与对象的应用—日期计算器

目录 一、前言 二、日期类的实现 检查日期的合法性 < 运算符重载 运算符重载 <运算符重载 >运算符重载 >运算符重载 !运算符重载 进一步优化 日期天数 日期天数 日期-天数 日期-天数 前置&&后置 前置--&&后置-- 思路&#…

强化学习的基础知识和6种基本算法解释

强化学习的基础知识和概念简介&#xff08;无模型、在线学习、离线强化学习等&#xff09; 机器学习(ML)分为三个分支:监督学习、无监督学习和强化学习。 监督学习(SL):关注在给定标记训练数据的情况下获得正确的输出无监督学习(UL):关注在没有预先存在的标签的情况下发现数据…

[附源码]Python计算机毕业设计Django校园疫情防范管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;我…

我的周刊(第070期)

我的信息周刊&#xff0c;记录这周我看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。&#x1f3af; 项目streamlit[1]用 Python 快速构建数据应用&#xff1…

微信公众号开发—通过网页授权实现业务系统登录及用户绑定(微信网页授权自动登录业务系统)

&#x1f60a; 作者&#xff1a; 一恍过去&#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390&#x1f38a; 社区&#xff1a; Java技术栈交流&#x1f389; 主题&#xff1a; 微信公众号开发—通过网页授权实现业务系统登录及用户绑定(微信网页授权自…

产品经理快速入门指南之常见问题篇

产品经理作为近几年互联网最炙手可热的岗位&#xff0c;可谓是赚足了眼球。其实呢&#xff0c;产品经理是很难定义的一个角色&#xff0c;如果非要一句话定义&#xff0c;那么产品经理是为终端用户服务&#xff0c;负责产品整个生命周期的人。今天这篇文章小编会带大家了解一下…

交通部1078-2016版中的音视频协议的一点想法

交通部1078的音视频中的格式有点像TS流, 交通部中1078的音视频的解析用的走的HTTP的协议,内容是流媒体,之前用的是ffmpeg解析的内容流之前是把payload中的数据流区分出音频,视频直接塞给ffmpeg,由ffmpeg推两路流到rtmp协议上去,这种方法有点粗暴, 最近分析ffmpeg源码发现交通…

谷歌通过Chrome简化登录安卓密码支持

谷歌宣布&#xff0c;它正在为其 Chrome 网络浏览器和 Android 操作系统引入密码支持&#xff0c;以简化跨应用程序、网站和设备的登录。 谷歌今天表示&#xff1a; “密码是密码和其他可钓鱼身份验证因素的一种更安全的替代品。它们不能重复使用&#xff0c;不会在服务器漏洞…

AngularJS 2.0 稳定版真的发布了!

导读之前我们还哀叹&#xff0c;谷歌的 AngularJS 2.0 的稳定版看起来年底也未必能见到&#xff0c;然而&#xff0c;在 9 月 14 日谷歌总部召开的一个会议上&#xff0c;突然就宣布最终的稳定版发布了——而这距离前一个版本 RC7 的发布才过去了一天。 AngularJS 2.0 的开发始…

详解入门安全测试最难懂的概念 —— CSRF

对于刚刚入门安全的同学来说&#xff0c;csrf是最难理解的概念之一&#xff0c;本文会用最简单的方式对csrf进行讲解&#xff0c;包括csrf的定义&#xff0c;csrf典型的攻击流程以及如何对其进行防范&#xff0c;希望本文能够帮到大家&#xff01; CSRF定义 CSRF&#xff08;…

Nacos学习笔记 (1)Nacos的简介与安装

1. Nacos 介绍与发展前景 1.1 官网概览&#xff1a; Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字母简称&#xff0c;一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一…

性能测试(一)—— 概述、策略、指标、流程

目录 一、性能测试概述 1、为什么要进行性能测试&#xff1f; 2、性能测试的概念 2.1 什么是性能&#xff1f; 2.2 什么是性能测试&#xff1f; 2.3 性能测试目的 3、性能测试与功能测试 3.1 焦点不一样 3.2 关系 二、性能测试策略 1、性能测试策略 1.1 基准测试 …

PageObject(PO)设计模式在 UI 自动化中的实践总结(以 QQ 邮箱登陆为例)

1080608 28.8 KB PO的思想最早是2013年由IT大佬Martin Flower提出的&#xff1a; martinfowler.com bliki: PageObject A page object wraps an HTML page, or fragment, with an application-specific API, allowing you to manipulate page elements for testing without d…

MVC操作方法如何绑定Stream类型的参数

1、我需要读取HTTP消息的整个 body 来填充 MVC 方法参数&#xff1b; 2、HTTP消息的 body 不是 form-data&#xff0c;而是完全的二进制内容。 最简单的方法就是不使用模型绑定&#xff0c;即在MVC方法中直接访问 HttpContext.Request.Body。 var request HttpContext.Requ…