无锁编程——从CPU缓存一致性讲到内存模型(1)

一.前言

1.什么是有锁编程,什么是无锁编程?

在编程中,特别是在并发编程的上下文中,“无锁”和“有锁”是描述线程同步和资源访问控制的两种不同策略。

有锁(Locked):
有锁编程是指使用锁(例如互斥锁、信号量等)来控制对共享资源的访问。在有锁策略中,线程必须在执行关键部分的代码前获得锁,以确保同一时间只有一个线程可以访问和修改共享资源。当线程完成对共享资源的操作后,它释放锁,使得其他线程可以接着访问资源。

特点包括:

线程安全:通过锁可以防止多个线程同时访问共享资源,避免竞争条件。
阻塞:线程在尝试获取一个已被其他线程持有的锁时,将会被阻塞,直到锁被释放。
开销:锁的获取和释放涉及操作系统层面的上下文切换,可能会导致较大的性能开销。
死锁:不正确的锁使用可能导致死锁,即两个或多个线程永久性地阻塞,等待彼此释放锁。

无锁(Lock-free):
无锁编程是一种不依赖于传统锁机制来控制共享资源访问的并发编程技术。无锁编程通常利用原子操作来确保即使在多个线程同时访问时,共享资源也能保持一致性。
那什么原子操作?

原子操作是指不可被中断的一个或一系列操作。它通过硬件支持来保证操作的原子性,通常使用特殊的CPU指令来实现。这些指令能够在单个步骤中完成读取-修改-写入的操作,而不会被其他线程中断。

上面提到的特殊指令->能够完成读取-修改-写入操作,指的是CAS(比较后交换技术)。为什么提到它,有什么用处?

这就要说到现代计算机的存储结构以及解决提升效率带来的一些硬件设备。


二.理解无锁编程需要的知识

1.存储结构

图片

可以看出L1和L2是每个核心都会有的。L3是一个处理器下的核心共有的。

主存(常规语境下所指的内存)是所有核心共有的。

越往下容量越大,同时读取速度越慢。

Cpu访问缓存的时候会有一个最小的读取单位,叫做cache line,一般是64个字节。

那么问题来了。为什么需要cache line ?(缓存),为什么这么设计?

因为:减少内存访问延迟:CPU的运行速度远远高于主内存的访问速度。Cache Line通过提供一个小而快速的存储,使得CPU能够更快地访问经常使用的数据和指令,从而减少了因等待内存访问而造成的延迟。

提高数据访问效率:由于数据访问通常具有空间局部性(连续的数据被一起访问),Cache Line作为一个数据块单位,可以一次性将多个连续的数据加载到缓存中。这样,当CPU访问其中一个数据时,很可能接下来的数据已经在缓存中了,从而提高了数据访问的效率。

带宽优化:与内存接口相比,CPU和缓存之间的数据带宽要宽得多。通过Cache Line,可以更有效地利用这带宽,因为每次传输都是传输一个数据块,而不是单个字节。

实现预取和并行处理:现代CPU通常具有预取机制,能够预测哪些数据将会被访问,并提前将数据加载到Cache中。Cache Line作为一个块单位,使得预取更加有效。同时,多核CPU可以利用Cache Line来并行处理数据,提高多任务处理的效率。

减少总线压力:如果没有缓存,CPU每次读写数据都要直接与内存通信,这会极大地增加总线上的数据流量。Cache Line允许CPU在大多数情况下与缓存而不是内存进行通信,从而减少了总线的压力。

提升能效:由于Cache Line减少了内存访问次数,因此也降低了内存功耗,整体上提升了系统的能效。

这种由cpu写到缓存而不是内存的策略叫做写回策略

三.写回策略

写直达策略:每次写操作会写到缓存中,也会写到内存中。写性能会很低,现代计算机很少使用了。

写回策略:尽量把数据存储到缓存之中,如果能写到缓存之中就避免写道内存中。

图片

 

是否命中缓存:是指之前的缓存中是否存有这个变量。

脏数据:缓存与内存不一致,或缓存有内存无的数据被标记为脏数据。

写数据的时候如果没有命中缓存,就利用LRU策略寻找到缓存中使用最少的区域,如果这块区域有数据并且是脏数据,那么将这块区域的数据刷入内存中。如果不是直接写入缓存。

读数据的时候如果没有命中缓存,先把数据从内存读入缓存,cpu再进行使用数据。

 

写回策略带来什么问题?

现代计算机结构有多个核心对应多个缓存,核心间共享的变量在不同的核心的缓存里内容不一样的问题。

如何解决?

四.MESI一致性协议

通过实现MESI一致性协议解决。他的内容及流程如下:

缓存一致性协议是确保多处理器系统中各个处理器的缓存数据一致性的机制。让我们详细讨论一下最常见的MESI(Modified, Exclusive, Shared, Invalid)协议的操作流程:

1. MESI协议状态:
   - Modified (M): 数据被修改,只在当前缓存中有效,与主存不一致。
   - Exclusive (E): 数据只在当前缓存中,未被修改,与主存一致。
   - Shared (S): 数据可能在多个缓存中存在,与主存一致。
   - Invalid (I): 缓存行无效。

2. 基本操作流程:

   a. 读操作:
      - 缓存未命中时:
        * 如果其他缓存有此数据(M或E状态),该缓存需先将数据写回主存。
        * 从主存读取数据,标记为S状态(如果其他缓存也有)或E状态(如果独占)。
      - 缓存命中时:
        * 如果是M、E或S状态,直接读取。
        * 如果是I状态,按缓存未命中处理。

   b. 写操作:
      - 缓存未命中时:
        * 如果其他缓存有此数据,需先使其无效。
        * 从主存读取数据,进行修改,标记为M状态。
      - 缓存命中时:
        * 如果是M状态,直接写入。
        * 如果是E状态,修改并变为M状态。
        * 如果是S状态,需先使其他缓存中的副本无效,然后修改并变为M状态。
        * 如果是I状态,按缓存未命中处理。

3. 状态转换:
   - I → E: 读取未被其他缓存持有的数据。
   - I → S: 读取被其他缓存共享的数据。
   - E → M: 修改独占的数据。
   - S → M: 修改共享的数据(需先使其他缓存副本无效)。
   - M → I, E → I, S → I: 其他处理器写入该数据。

4. 总线操作:
   - Read: 请求读取数据。
   - Read with Intent to Modify (RWITM): 请求读取并修改数据。
   - Invalidate: 使其他缓存中的副本无效。
   - Writeback: 将修改后的数据写回主存。

5. 协议执行流程:
   a. 处理器发出内存访问请求。
   b. 检查本地缓存状态。
   c. 根据状态和操作类型,可能需要发起总线事务。
   d. 其他处理器监听总线,根据需要更新自己的缓存状态。
   e. 完成数据访问或修改。

上面我们提到了CAS,与缓存一致性的关系?

五.CAS

CAS:是实现原子操作和无锁数据结构的基础。

function CAS(M, A, B) isif M == AM ← Breturn trueelsereturn false

它是一种原子操作,它比较内存位置的内容与给定值,只有在相同的情况下,才会将该内存位置的内容修改为新的给定值。

CAS与缓存一致性的关系就是需要CAS在写回策略的环境中维护正确性和高效性,这需要硬件层面的支持和软件的安全编程。

六.内存序和内存屏障

C++中原子操作往往有一个参数是规定内存序,用于指导编译器进行优化,用于指导cpu进行指令重排。可以解决两个问题,一是变量更新是否能马上被其他线程看到,二是代码顺序性的问题。

那么问题来了,为什么会有内存序问题?

因为编译器和cpu会在判断代码顺序不影响程序的情况下,有可能会重排相邻的代码执行顺序。比如一个线程锁住了一块内存空间,另一个线程无法操作那块内存空间,这项操作之后的操作并不刚需这块内存空间,这时候可能会重排先往后执行。这是为了提升整个系统的性能,但有时我们要求一定要按某个顺序执行,那么就有时候就不允许重排操作。

内存序和内存屏障是为了解决现代计算机系统中由于硬件优化和多核处理器引起的内存访问复杂性问题

内存序:指定了内存操作的可见性和顺序性规则。

内存屏障:用于强制执行特定的内存操作顺序的硬件指令。

内存序和内存屏障的关系
   - 内存序是高级抽象,定义了操作的语义。
   - 内存屏障是底层实现机制,用于实现内存序。

 C++11原子变量内存序的相关参数

见:std::memory_order - cppreference.com std内存屏障API,

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

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

相关文章

Python系统教程01

Python 是一门解释性语言,相对更简单、易学,它可以用于解决数学问题、获取与分 析数据、爬虫爬取网络数据、实现复制数学算法等等。 1、print()函数: print()书写时注意所有的符号都是英文符号。print()输出内容时,若要输出字符…

大力出奇迹:大语言模型的崛起与挑战

随着人工智能(AI)技术的迅猛发展,特别是在自然语言处理(NLP)领域,大语言模型(LLM)的出现与应用,彻底改变了我们与机器互动的方式。本文将探讨ChatGPT等大语言模型的定义、…

回溯 | Java | LeetCode 39, 40, 131 做题总结(未完)

Java Arrays.sort(数组) //排序 不讲究顺序的解答,都可以考虑一下排序是否可行。 39. 组合总和 错误解答 在写的时候需要注意,sum - candidates[i];很重要,也是回溯的一部分。 解答重复了。是因为回溯的for循环理解错了。 class Solutio…

力扣热100 哈希

哈希 1. 两数之和49.字母异位词分组128.最长连续序列 1. 两数之和 题目:给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。…

34. 在排序数组中查找元素的第一个和最后一个位置(中等)

34. 在排序数组中查找元素的第一个和最后一个位置 1. 题目描述2.详细题解(1)朴素二分查找算法(2)改进二分查找算法 3.代码实现3.1 Python  方法一:  方法二:  方法三:优化方法二 3.2 Java 1. 题目描述 题目中转…

Elasticsearch:Painless scripting 语言(二)

这是继上一篇文章 “Elasticsearch:Painless scripting 语言(一)” 的续篇。 使用 field API 访问文档中的字段 警告:Field API 仍在开发中,应视为测试版功能。API 可能会发生变化,此迭代可能不是最终状态。…

Ubuntu20.04 安装 cudatookit 12.2 + cudnn 安装

最简约的部署Ubuntu20.04深度学习环境的教程 1. 安装Ubuntu20.04 系统 B站详细的安装教程 简约安装版 2. 安装Nvidia显卡驱动 我参考了各种资料,重装系统,完美解决开机显示器黑屏无法进入桌面的情况 黑屏问题主要是由linux内核更新导致,…

煤矿ar远程协作平台系统提升了操作的安全性和效率

工业AR远程专家协助系统为企业量身打造大型设施的虚拟布局方案。借助先进的AR增强现实技术,企业能够在虚拟环境中精准模拟并购买适配设备,确保设施的顺畅运行。同时,工业AR远程专家协助系统能提供的协作功能让团队成员能够实时共享虚拟布局&a…

昇思25天学习打卡营第8天|MindSpore-SSD目标检测

SSD目标检测介绍 SSD,全称Single Shot MultiBox Detector,是Wei Liu在ECCV 2016上提出的一种目标检测算法。使用Nvidia Titan X在VOC 2007测试集上,SSD对于输入尺寸300x300的网络,达到74.3%mAP(mean Average Precision)以及59FPS;对于512x512的网络,达到了76.9%mAP ,超…

Mouse Albumin ELISA Kit小鼠白蛋白ELISA试剂盒

白蛋白存在于所有哺乳动物和许多低等脊椎动物的血管内和血管外,是一种由肝脏合成的约67kDa的蛋白质。正常情况下,只有非常微量的白蛋白能逃过肾小球的重吸收,并被排泄到尿液中。ICL的Mouse Albumin ELISA Kit是一种高灵敏度的双抗体夹心法ELI…

基于“香港世界”的SLAM技术介绍

在视觉感知技术中,理解和描述复杂的三维室外场景至关重要,尤其是自动驾驶技术的发展要求对陌生环境具有更强的适应能力和鲁棒性。传统上,使用“曼哈顿世界”和“亚特兰大世界”模型来描述具有垂直和水平结构的城市场景。 当遇到像香港这样地形…

某安全公司DDoS攻击防御2024年6月报告

引言: 在2024年6月,网络空间的安全挑战汹涌澎湃。分布式拒绝服务(DDoS)攻击频发,针对云服务、金融科技及在线教育平台的精密打击凸显出当前网络威胁环境的严峻性。 某安全公司作为网络安全防护的中坚力量&#xff0c…

代码随想录算法训练营Day55|42.接雨水、84.柱状图中最大的矩形

接雨水 42. 接雨水 - 力扣(LeetCode) 暴力解法 对计算接到的雨水,有两种方式,一是按照行来计算。 另一种是按列计算 按列计算容易不乱。基本思路如下: 对每列i进行循环,在循环中,找到该列左…

HarmonyOS Next开发学习手册——视频播放 (Video)

Video组件用于播放视频文件并控制其播放状态,常用于为短视频和应用内部视频的列表页面。当视频完整出现时会自动播放,用户点击视频区域则会暂停播放,同时显示播放进度条,通过拖动播放进度条指定视频播放到具体位置。具体用法请参考…

寒武纪实现高维向量的softmax进阶优化和库函数对比

关于寒武纪编程可以参考本人之前的文章添加链接描述,添加链接描述,添加链接描述 实验证明,axis=0和axis=-1的时候,手写softmax速度可以和库函数媲美,甚至于更甚一筹。 src/softmax.mlu #include <bang.h> #include

Nik Collection by DxO:摄影师的创意利器与调色宝典

在数码摄影的世界里&#xff0c;后期处理是摄影师们展现创意、调整细节、提升作品质量的重要步骤。而Nik Collection by DxO作为一款由DxO公司开发的强大照片编辑插件套件&#xff0c;为摄影师们提供了一套全面的、功能丰富的工具集&#xff0c;让他们的创意得以充分发挥。 Ni…

遇到多语言跨境电商系统源码问题?这里有解决方案!

从手机到电脑&#xff0c;从线下到线上&#xff0c;如今&#xff0c;跨境电商正在打破地域界限&#xff0c;成为全球贸易的新引擎。在这个全球化的背景下&#xff0c;跨境电商平台的运营也面临着一系列的挑战&#xff0c;其中之一就是多语言问题。如果你遇到了多语言跨境电商系…

2065. 最大化一张图中的路径价值 Hard

给你一张 无向 图&#xff0c;图中有 n 个节点&#xff0c;节点编号从 0 到 n - 1 &#xff08;都包括&#xff09;。同时给你一个下标从 0 开始的整数数组 values &#xff0c;其中 values[i] 是第 i 个节点的 价值 。同时给你一个下标从 0 开始的二维整数数组 edges &#xf…

7基于SpringBoot的SSMP整合案例-表现层开发

目录 1.基于Restfu1进行表现层接口开发 1.1创建功能类 1.2基于Restful制作表现层接口 2.接收参数 2使用Apifox测试表现层接口功能 保存接口&#xff1a; 分页接口&#xff1a; 3.表现层一致性处理 3.1先创建一个工具类&#xff0c;用作后端返回格式统一类&#xff1a;…

springboot校园购物网站APP-计算机毕业设计源码041037

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存…