浅析内存一致性:内存屏障

文章目录

    • 概述
    • 内存乱序访问
      • Store Buffer和Invalidate Queue
        • Store Buffer
          • Store Forwarding
          • Store Buffer与内存屏障
      • Invalidate Queue
        • Invalidate Queue与内存屏障
    • 内存屏障分类
        • 编译器屏障
        • CPU内存屏障
    • 相关参考

概述

内存屏障,是一类同步屏障指令,是CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后才可以执行此点之后的操作。内存屏障的产生是为了解决程序在运行过程中所产生的内存乱序访问问题。

内存乱序访问

若程序在执行时的实际内存访问顺序和程序代码编写的访问顺序不一致,这就是内存乱序访问。内存乱序访问的出现是为了提升程序执行时的效率,主要发生在两个阶段:

  • 编译时,编译器优化导致内存乱序访问(指令重排);
  • 运行时,多CPU交互引起内存乱序访问,通常是硬件层面的优化所导致,主要包括以下两个方面:
    • 现代CPU采用指令并行技术,引入指令执行级别的乱序优化,如流水线、乱序执行、分支预测等造成的乱序;
    • 现代CPU采用内部缓存技术,导致数据的变化不能及时反映到内存中,如硬件级别Cache一致性优化引入的Store Buffer和Invalidate Queue等组件造成的乱序。

Store Buffer和Invalidate Queue

MESI协议解决了缓存一致性问题, 但是其自身也存在一个性能弱点——处理器执行写内存操作时,必须等待其他所有处理器将其高速缓存中的相应副本数据删除并接收到这些处理器所回复的 Invalidate Acknowledge/Read Response消息之后才能将数据写入高速缓存。
在这里插入图片描述

为了规避和减少这种等待造成的写操作的延迟 (Latency),硬件设计者引入了Store Buffer和Invalidate Queue,用于优化缓存一致性协议的性能,与此同时,也导致了一些内存乱序的问题。

Store Buffer

Store Buffer是处理器内部的一个容量比Cache还小的私有高速存储部件,每个处理器都有其Store Buffer,并且一个处理器无法读取另外一个处理器上的Store Buffer中的内容。
在这里插入图片描述

引入Store Buffer后,处理在执行写操作时的行为如下:

缓存状态操作
Exclusive/Modified处理器可能会直接将数据写入相应的缓存行而无需发送任何消息(取决于具体处理器的实现)
Shared处理器会先将写操作的相关数据存入Store Buffer中,并发送Read Invalidate消息
Invalid处理器的高速缓存不含有待操作的数据,遇到了写未命中(Write Miss),处理器会先将写操作的相关数据写入Store Buffer,并发送Read Invalidate消息,此后处理器继续运行

在写数据之前我们先要得到缓存行的独占权,如果当前CPU没有独占权,要先让系统中别的CPU上缓存的同一段数据都变成无效状态。为了提高性能,可以引入一个叫做Store Buffer的模块,将其放置在每个CPU和它的缓存之间。当前CPU发起写操作,如果发现没有独占权,可以先将要写入的数据放在存储缓冲中,并继续运行,仿佛独占权瞬间就得到了一样。当然,存储缓冲中的数据最后还是会被同步到缓存中的,但就相当于是异步执行了,不会让CPU等了。并且,当前CPU在读取数据的时候应该首先检查其是否存在于存储缓冲中。

Store Forwarding

允许处理器直接从Store Buffer中读取数据来实现内存读操作的技术被称为存储转发(Store Forwarding)。 存储转发使得写操作的执行处理器能够在不影响该处理器执行读操作的情况下将写操作的结果存入写缓冲器。
在这里插入图片描述

Store Buffer与内存屏障

在这里插入图片描述

Invalidate Queue

如果当前CPU上收到一条消息,要使某个缓存段失效,但是此时缓存正在处理其它事情,那这个消息可能无法在当前的指令周期中得到处理,而会将其放入所谓的Invalidation Queue中,同时立即发送使无效应答消息。那个待处理的使无效消息将保存在队列中,直到缓存有空为止。
在这里插入图片描述

Invalidate Queue与内存屏障

在这里插入图片描述

内存屏障分类

内存屏障允许软件开发者使用硬件提供的特殊指令控制编译器和CPU的行为,在可能存在并发访问问题的点禁止编译器指令重排和CPU对指令乱序执行。为了解决上述的内存访问乱序问题,系统提供了两种类型的内存屏障:编译器屏障和CPU内存屏障。

编译器屏障

编译器屏障用于阻止编译器进行指令重排,保证其在编译程序时,在优化屏障之前的指令不会在优化屏障之后执行。编译器提供了barrier() 宏实现编译器屏障:

#define barrier() __asm__ __volatile__("": : :"memory") 

需要注意的一点是,barrier()只会约束编译时的指令重排行为,不约束CPU运行时的行为,CPU仍然可以乱序执行程序。

CPU内存屏障

CPU内存屏障用于防止CPU运行时指令之间的重排序行为,并保证数据对其它CPU的可见性。CPU内存屏障通常可分为三类:

  • 通用屏障,保证读写操作有序;
  • 读操作屏障,仅保证读操作有序;
  • 写操作屏障,仅保证写操作有序。

相关参考

  • 《Memory Barriers: a Hardware View for Software Hackers​》
  • 《A Primer on Memory Consistency and Cache Coherence》
  • 多种内存一致性模型的特性分析
  • 第五章:乱序执行
  • 计算机体系结构-重排序缓存ROB

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

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

相关文章

分布式锁3: zk实现分布式锁2 使用临时节点(需要自旋)

一 使用临时节点实现分布式锁 1.1 代码截图 1.2 代码如下 由于zookeeper获取链接是一个耗时过程,这里可以在项目启动时,初始化链接,并且只初始化一次。借助于spring特性,代码实现如下: package com.atguigu.distri…

Spring MVC MVC介绍和入门案例

1.SpringMVC概述 1.1.MVC介绍 MVC是一种设计模式,将软件按照模型、视图、控制器来划分: M:Model,模型层,指工程中的JavaBean,作用是处理数据 JavaBean分为两类: 一类称为数据承载Bean&#xf…

逆向数据宽度与符号

正数与负数的 刚好是半 所以 0 表示正数 1表示负数 有符号与无符号是程序员定的 并不是开头是1就表示负数 0表示正数 得看有无符号 双字 32bit 4字节

【UE Niagara学习笔记】04 - 火焰喷射时的黑烟效果

目录 效果 步骤 一、创建烟雾材质 二、添加新的发射器 三、设置新发射器 3.1 删除Color模块 3.2 减少生成的粒子数量 3.3 设置粒子初始颜色 3.4 设置烟雾的位置偏移 3.5 设置烟雾淡出 在上一篇博客(【UE Niagara学习笔记】03 - 火焰喷射效果&#xf…

机器学习(四) -- 模型评估(4)

系列文章目录 机器学习(一) -- 概述 机器学习(二) -- 数据预处理(1-3) 机器学习(三) -- 特征工程(1-2) 机器学习(四) -- 模型评估…

【JAVA】怎么确保一个集合不能被修改

🍎个人博客:个人主页 🏆个人专栏: JAVA ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 示例: 不可修改的List: 不可修改的Set: 不可修改的Map: 结语 我的其他博…

SpringBoot 如何增强PageHelper入参的健壮性

PageHelper.startPage(int pageNum, int pageSize, boolean count) 参数为外部输入,故存在异常输入场景。比如 pageNum 和 pageSize 输入的值 负数 或者 0,所以引入PageUtils来对入参进行判断矫正,从而避免引入异常。 第1步:支持…

conda新建、配置python3.8虚拟环境,torch-cuda1.8,torchtext0.9.0,huggingface安装transformers库

起因是我在用bert的时候,导包报错 Python 环境缺少 importlib.metadata 模块。importlib.metadata 是 Python 3.8 引入的模块,而我的环境中使用的 Python 版本为 3.7。所以我得重新配置一个python3.8的环境 准备工作 在开始菜单找到anaconda prompt(an…

Vscode中的node.js的安装与使用

前往官网下载安装包 Node.js 中文网 选择较为稳定的版本 安装全选下一步就好了,这里可以选择配置环境变量是否自动启动node.js 在控制台输入指令如果出现了版本号就代表成功了

flex布局(3)

九、骰子 *{margin:0;padding: 0;box-sizing: border-box; } .flex{display: flex;flex-flow: row wrap;justify-content: space-between;align-items: center;align-content: space-between;padding:20px; } .touzi{width: 120px;height: 120px;background-color: aliceblue;…

Java网络爬虫--HttpClient

目录标题 技术介绍有什么优点?怎么在项目中引入? 请求URLEntityUtils 类GET请求带参数的GET请求POST请求 总结 技术介绍 HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、功能丰富的、支持 HTTP 协议的客户端编程工具包。相…

开启Android学习之旅-6-实战答题App

不经过实战,看再多理论,都是只放在笔记里,活学活用才是硬道理。同时开发应用需要循序渐进,一口气规划300个功能,400张表,会严重打击自己的自信。这里根据所学的,开发一个答题App。 题库需求分析…

QML 模型视图

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 对于 GUI 应用程序来说,我们通常需要格式化数据并进行显示,而 QML 提供了一种很便利的显示方式 - Model-View-Delegate(简称:MVD)。该模式是 Model-View-Controller(简称:MVC)的一种变体,常被用于分…

HackTheBox - Medium - Linux - Awkward

Awkward Awkward 是一款中等难度的机器,它突出显示了不会导致 RCE 的代码注入漏洞,而是 SSRF、LFI 和任意文件写入/追加漏洞。此外,该框还涉及通过不良的密码做法(例如密码重用)以及以纯文本形式存储密码来绕过身份验…

力扣:18.四数之和

一、做题链接:18. 四数之和 - 力扣(LeetCode) 二、题目分析 1.做这一道题之前本博主建议先看上一篇《三数之和》 2.题目分析 给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重…

计算机毕业设计 基于SpringBoot的项目申报系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍:✌从事软件开发10年之余,专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ 🍅文末获取源码联系🍅 👇🏻 精…

程序媛的mac修炼手册-- 终端(terminal)常用命令

「终端(terminal)」相当于macOS的一个 App ,它的特殊之处是,它是管理其它App的App,操作主要通过命令行界面 (CLI) 。 相比于我们日常熟悉的用户界面(User Interface,UI)&#xff0c…

Redis 主从、哨兵和分片集群简单介绍

Redis 主从集群架构 单节点 redis 并发能力有上限,要进一步提高 redis 并发能力,就要搭建主从集群,实现读写分离 主从同步原理 Replicaition id:每台 master 机器都一个 repl_id,是数据集的表示,若 salv…

软件测试|如何在Pycharm中配置文件头部信息

简介 PyCharm是一款功能强大的Python集成开发环境(IDE),在开发过程中,我们经常需要在代码文件的开头添加固定的文件说明信息,例如版权声明、作者信息、创建日期等。手动添加这些信息可能会很繁琐,但是PyCh…

[Vulnhub靶机] DriftingBlues: 5

[Vulnhub靶机] DriftingBlues: 5靶机渗透思路及方法(个人分享) 靶机下载地址: https://download.vulnhub.com/driftingblues/driftingblues5_vh.ova 靶机地址:192.168.67.24 攻击机地址:192.168.67.3 一、信息收集 …