内存屏障由来的理解和使用《编程高手必学的内存知识》学习笔记 Day 5

news2024/11/17 2:57:13

系列文章目录

这是本周期内系列打卡文章的所有文章的目录

  • 《Go 并发数据结构和算法实践》学习笔记 Day 1
  • 《Go 并发数据结构和算法实践》学习笔记 Day 2
  • 《说透芯片》学习笔记 Day 3
  • 《深入浅出计算机组成原理》学习笔记 Day 4

文章目录

  • 系列文章目录
  • 前言
  • 一、概念理解(What)
  • 二、内存屏障,解决方案发展的脉络(How、Why)
  • 三、延伸学习
  • 总结


前言

提示:这里可以添加本文要记录的大概内容:

学习内容:https://time.geekbang.org/column/article/462113
知识主客体建立关系:
之前研究DPDK无锁队列,看到实现中有些读屏障和写屏障,只是模糊理解个大概,但不知道它在什么时候出问题,所有用屏障保证时序正确性。现在看了这篇文章,理解了读写屏障解决store buffer引入的问题,读屏障解决invalid queue问题,两个异步化设计提升性能之后,要兼容Cache机制协议,保证程序在多核上时序正确。


提示:以下是本篇文章正文内容,下面案例可供参考

一、概念理解(What)

这点文章解释得很清楚,我整理一下从文章中学到的概念。

  1. buffer和cache的区别:打个比喻,cache 往往意味着它所存储的信息是副本,但是 buffer 更像是蓄水池,buffer 中的数据没有副本,一旦丢失就彻底丢失了。两者都是结构性的优化,cache 存在的意义是加速查找
  2. store buffer 作为buffer结构引入的设计,是硬件实现的缓冲区,自然它的读写速度比缓存的速度更快,看下图就懂了。先搜集多次写操作,然后在合适的时机进行提交,作为CPU私有,同样需要兼容对应的缓存协议。

在这里插入图片描述

store buffer 的存在是为提升写性能,放弃了缓存的顺序一致性,我们把这种现象称为弱缓存一致性

  1. 内存屏障,屏障的作用是前边的读写操作未完成的情况下,后面的读写操作不能发生。如Arm 上 dmb 指令。

  2. 失效队列:

由于 store buffer 的存在提升了写入速度,那么 invalid 消息确认速度相比起来就慢了,这就带来了速度的不匹配,很容易导致 store buffer 的内容还没有及时更新到 cache 里,自己的容量就被撑爆了,从而失去了加速的作用。为了解决这个问题,CPU 设计者又引入了“invalid queue”

如下图:
在这里插入图片描述
5. 读写屏障分离
分离的写屏障和读屏障的出现,是为了更加精细地控制 store buffer 和 invalid queue 的顺序。

  1. 单向屏障

(half-way barrier) 也是一种内存屏障,但它并不是以读写来区分的,而是像单行道一样,只允许单向通行,例如 Arm 中的 stlr 和 ldar 指令就是这样。
stlr 的全称是 store release register,也就是以 release 语义将寄存器的值写入内存;ldar 的全称是 load acquire register,也就是以 acquire 语义从内存中将值加载入寄存器。我们重点就来看看 release 和 acquire 语义。

语义对比
release 语义挡前不挡后
acquire 语义挡后不挡前

二、内存屏障,解决方案发展的脉络(How、Why)

  1. 用 store buffer 也会有一个问题,那就是它并不能保证变量写入缓存和主存的顺序,这也就需要引入内存屏障。

一个代码示例,可以用GEM5 CPU仿真做成验证实验:


// CPU0
void foo() {
    a = 1;
    b = 1;
}

// CPU1
void bar() {
    while (b == 0) continue;
    assert(a == 1);
}

在这个代码块中,CPU0 执行 foo 函数,CPU1 执行 bar 函数。但在对变量 a 和 b
进行赋值的时候,有两种情况会导致它们的赋值顺序被打乱。

第一种情况是 CPU 的乱序执行。 CPU 为了提升运行效率和提高缓存命中率,采用了乱序执行。
第二种情况是 store buffer 在写入时,有可能 b 所对应的缓存行会先于 a
所对应的缓存行进入独占状态,也就是说 b 会先写入缓存。

  1. 由于 store buffer 的存在提升了写入速度,那么 invalid 消息确认速度相比起来就慢了,这就带来了速度的不匹配,很容易导致 store buffer 的内容还没有及时更新到 cache 里,自己的容量就被撑爆了,从而失去了加速的作用。为了解决这个问题,CPU 设计者又引入了**“invalid queue”**

极客时间版权所有: https://time.geekbang.org/column/article/462113
3. 分离的写屏障和读屏障的出现,是为了更加精细地控制 store buffer 和 invalid queue 的顺序

三、延伸学习

内存屏障是硬件篇,其中不同体系结构CPU的设计,都有各有特色的方案及取舍。可以延伸的点也很多:

  1. X86的模型:为啥X86 采用的 TSO 模型不存在缓存一致性的问题
  2. ARM的CPU设计:通过单向通行来区分屏障
  3. alpha体系结构:通过读写来区分屏障
  4. 语言层面,如Java的Unsafe对内存屏障的抽象和支持
  5. 从MESI延伸出弱缓存一致性协议,具体协议细节等
  6. 内存屏障生产方案的使用案例:DPDK无锁队列实现等

总结

提示:这里对文章进行总结:

内在脉络,软件开发随着硬件设计而发展:

CPU 从单核发展为多核,增加缓存,导致出现了多个核间的缓存一致性问题 --> 为了解决缓存一致性问题,提出了 MESI 协议 --> 完全遵守 MESI 又会给 CPU 带来性能问题 --> CPU 设计者又增加 store buffer 和 invalid queue --> 又导致了缓存的顺序一致性变为了弱缓存一致性 --> 需要缓存的顺序一致性的,就需要软件工程师自己在合适的地方添加内存屏障。

内容来源:
极客时间:16 | 编程高手必学的内存知识

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

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

相关文章

JUC面试(六)——Java锁

Java锁 公平锁和非公平锁 概念 公平锁 是指多个线程按照申请锁的顺序来获取锁,类似于排队买饭,先来后到,先来先服务,就是公平的,也就是队列 非公平锁 是指多个线程获取锁的顺序,并不是按照申请锁的顺…

steam搬砖项目,每天1-2小时,月入1w+(内附教学资料)

steam搬砖就非常合适,最大的优点,操作性简单,0门槛也不用担心,一台电脑就能搞定。利用空余时间完成就可以 话不多说,先上目录,以便大家阅读~ 一.steam搬砖玩法 1、steam搬砖项目介绍 2、项目原理与产出…

ROS2机器人编程简述humble-第二章-Parameters .3.4

ROS2机器人编程简述humble-第二章-Launchers .3.3机器人程序通常需要配置各类参数,官网和一些书中都有介绍。概述ROS中的参数与各个节点相关。参数用于在启动时(以及运行时)配置节点,而无需更改代码。参数的生存期与节点的生存期相…

【区块链】深入剖析免费赚钱app的本质

你对免费赚钱软件好奇吗?前言一、揭开“免费赚钱app”神秘面纱1.常见的赚钱app2.app真的在做慈善吗?3.羊毛党的价值4.真正的游戏规则二、区块链1.哈希算法2.互联网挖矿三、深入探讨“区块链”的套路1.免费赚钱app真正的价值2.虚拟货币的本质3.虚拟货币泡…

Java设计模式-观察者模式/观察者模式适合那些场景?怎么使用

继续整理记录这段时间来的收获,详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用! 6.7 观察者模式 6.7.1 定义 又称发布-订阅模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象主体对象在状态变化…

[前端笔记——CSS] 9.CSS处理文件的标准流程+DOM

[前端笔记——CSS] 9.CSS处理文件的标准流程DOM1.CSS处理文件的标准流程2.关于DOM2.1 举个例子2.2 应用 CSS 到 DOM1.CSS处理文件的标准流程 当浏览器展示一个文件的时候,它必须兼顾文件的内容和文件的样式信息,CSS处理文件的标准流程如下: …

06_FreeRTOS临界区代码保护

目录 临界段代码保护简介 临界段代码保护函数介绍 任务级临界区函数详解 中断级临界区函数详解 临界段代码保护简介 什么是临界段:临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段 适用场合如: 1.外设:需严格按照时序初始化的外设:IIC、SPI等等 2.系统…

国家发明专利:基于改进型黏菌优化算法的业务资源分配方法

国家发明专利:基于改进型黏菌优化算法的业务资源分配方法 摘要 本发明公开了一种基于改进型黏菌优化算法的业务资源分配方法,其步骤包括:1将生产任务分成若干个环节,构建有向环状分配网络;2构建工厂参数矩阵并归一化&…

力扣98.验证二叉搜索树

文章目录力扣98.验证二叉搜索树题目描述算法思路代码实现力扣98.验证二叉搜索树 题目描述 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左子树只包含 小于 当前节点的数。 节点的右子树只包含 …

领域驱动设计(DDD)的几种典型架构介绍

我们生活中都听说了DDD,也了解了DDD,那么怎么将一个新项目从头开始按照DDD的过程进行划分与架构设计呢? 一、专业术语 各种服务 IAAS:基础设施服务,Infrastructure-as-a-service PAAS:平台服务&#xff0c…

【Java寒假打卡】JavaWeb-Servlet基础

【Java寒假打卡】JavaWeb-Servlet基础介绍servlet快速入门servlet的执行过程servlet关系视图Servlet实现方式-继承HTTPSERVLETServlet的生命周期线程安全问题servlet的映射方式案例-多路径映射问题-指定名称的方式Servlet的创建时机默认Servlet介绍 servlet是运行在Java服务器…

免费分享一套 SpringBoot + Vue + ElementUI 的人力资源管理系统,挺漂亮的

大家好,我是锋哥,看到一个不错的SpringBoot Vue ElementUI 的人力资源管理系统,分享下哈。 项目介绍 项目背景 人力资源管理是企业运营中必不可少的一环,它关系到企业的前途与发展。尤其对于中小微企业来说,对企业…

积分分离PID控制算法及仿真-1

在普通 PID 控制中引入积分环节的目的,主要是为了消除静差,提高控制精度。但在过程的启动、结束或大幅度增减设定时,短时间内系统输出有很大的偏差,会造成PID运算的积分积累,致使控制量超过执行机构可能允许的最大动作…

Vue项目基础环境搭建完整步骤

使用vue官方脚手架(vue-cli) vue-cli简介 Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统,是一个官方脚手架,可以帮助我们快速创建vue项目工程目录,目前最新版本4.x。 Vue CLI 致力于将 Vue 生态中的工具基础标准化。它确保了各种构建…

第三天总结 之 商品管理界面的实现 之 模糊查询 与 数据在页面展示

商品管理界面的实现 模糊查询 第一步: 明确 查询时 需要的 条件 即sql语句中 where 后的条件 如 : 根据前端 可以发现 模糊查询可以通过 商品名称 日期 商品类型 来查询 所以在对应的controller层下的GoodsFuzzySelectServlet中首先要获取这三个属性的…

《深入浅出计算机组成原理》学习笔记 Day6

二进制编码1. “逢二进一”2. 字符串的表示参考1. “逢二进一” 把一个二进制数对应到十进制,就是把从右到左的第 N 位,乘上一个2 的 N 次方,然后加起来,就成了一个十进制数。从右到左的位置,是从 0 开始的。 例如&a…

初识C语言:IDE的选择与使用【C语言】

本文是本专栏【C语言】的第一篇文章,也是博主最近半年以来的更新第一篇文章,如果觉得有帮助,可以点赞支持一下!另外本专栏最后会做一篇类似于【python爬虫】专栏最后的那篇整合的文章,把C语言的所有基础知识用一篇文章…

深度学习 GNN图神经网络(三)模型思想及文献分类案例实战

如果你有一定神经网络的知识基础,想学习GNN图神经网络,可以按顺序参考系列文章: 深度学习 GNN图神经网络(一)图的基本知识 深度学习 GNN图神经网络(二)PyTorch Geometric(PyG&#x…

Nginx入门与应用

NginxNginx概述Nginx介绍Nginx下载和安装windowsLinuxNginx目录结构Nginx命令查看版本检查配置文件正确性启动和停止重新加载配置文件Nginx环境变量(Linux)Nginx配置文件结构Nginx具体应用部署静态资源反向代理负载均衡Nginx概述 Nginx介绍 Nginx是一款…

Linux系统——基础IO

要努力,但不要着急,繁花锦簇,硕果累累,都需要过程! 目录 1.文件基础必备概念 2.文件系统调用接口 1.open && close 2.write 3.read 3.文件描述符fd 3.1什么是文件描述符 3.2文件描述符意义 3.3文件描述符的分配…