X86 原子 RMW 指令是否空闲等待

2024-01-03

在 x86 上,原子 RMW 指令如lock add dword [rdi], 1在现代 CPU 上使用高速缓存锁定来实现。因此,高速缓存行在指令执行期间被锁定。这是通过在读取值时获取行 EXCLUSIVE/MODIFIED 状态来完成的,并且 CPU 在指令完成之前不会响应来自其他 CPU 的 MESI 请求。

并发进度条件有两种类型:阻塞和非阻塞。原子 RMW 指令是非阻塞的。 CPU 硬件在持有高速缓存锁时永远不会休眠或执行其他操作(中断发生在原子 RMW 之前或之后,而不是期间),释放高速缓存行之前的步骤数有一个有限(且很小)的上限。

非阻塞算法 https://en.wikipedia.org/wiki/Non-blocking_algorithm在理论计算机科学中可以分为三种类型:

  1. wait free:所有线程都将在有限的步骤中取得进展。

  2. 无锁:至少一个线程将在有限数量的步骤中取得进展

  3. 无阻塞:如果没有争用,线程将在有限数量的步骤中取得进展

x86提供什么样的保证?

我猜它至少是无锁的;如果存在争用,则至少有一个 CPU 会取得进展。

但是 x86 可以免费等待原子指令吗?是否每个 CPU 都能保证在有限数量的步骤中取得进展,或者是否可能有一个或多个 CPU 资源匮乏并可能无限期延迟?

那么当多个核心在同一缓存行上执行原子操作时会发生什么?


考虑更普遍的问题:如果有多个活动硬件线程,x86 是否保证每个线程都能向前推进,而不管其他线程做什么?您提出的问题似乎专门针对每个线程同时对重叠内存位置执行原子指令的情况。如果答案是肯定的,那么 x86 可谓“免等待”。 (该术语通常仅用于描述线程同步算法,但无论如何。)

我认为从架构或其实现的角度定义“向前进展”的含义很重要。我不喜欢在定义中使用术语“步骤”,因为不清楚什么是步骤,什么不是步骤。相反,我将使用以下定义:当活动硬件线程按程序顺序完成下一个动态指令时,通过将其退出或在出现错误情况下切换到异常处理程序来向前推进。如果每个活动的硬件线程都可以在有限的时间内取得进展,而不管其他线程做什么,也不管每个线程正在执行什么指令,只要它们不会导致线程变得不活动,那么 x86 就会等待 -自由的。 (请注意,中断处理程序不是在硬件线程上执行的程序的一部分,因此处理中断并不意味着线程正在向前推进。)

每个 CPU 都能保证在有限的步骤中取得进展吗 或者可能是一个或多个 CPU 资源不足并且可能 可能无限期推迟?

您可能会想到,如果有两个核心不断尝试获取对同一位置的原子 RMW 访问,则其中一个总是会成功,而另一个总是会失败,因为尝试执行相同的原子指令而没有取得任何进展,因此陷入困境它是程序顺序中的下一条指令。

这实际上是计算机体系结构中的一个传统问题。我想考虑更普遍的问题的原因是,除了获取锁之外,多个硬件线程或代理之间还存在许多可能的争用点。考虑一下你所说的:

CPU 硬件在保持状态时永远不会休眠或做其他事情 缓存锁(中断发生在原子 RMW 之前或之后,而不是 期间),数量有一个有限(且很小)的上限 释放缓存行之前的步骤。
...
我猜它至少是无锁的;如果存在争用,则至少有一个 CPU 会取得进展。

Intel和AMD从未声明过“释放缓存线之前的步数有一个有限的上限”。这种推理几乎可以应用于指令执行的任何阶段。如果私有缓存中的提取丢失,提取指令的步骤数是否存在有限上限?从共享缓存读取值的步骤数是否存在有限上限?对于超线程,几乎在执行任何类型指令的每个阶段都存在潜在的争用。你可以对他们每个人问同样的问题。原子访问争用并不特殊。人们还可以提出其他问题,例如核心是否有可能任意进入睡眠状态并且永远不会醒来。

从根本上讲,如果不通过设计在架构级别确保每个核心只要处于活动状态(根据上面的定义)就始终能够取得进展,那么拥有多个核心是没有意义的。否则,无法充分利用实施。每个实际的 ISA 都必须提供最小的前向进度保证,即任何操作都需要有限的时间来完成,并且在全局(或多代理)操作顺序中先于有限数量的其他操作。一些 ISA(例如 RISC-V)确实明确声明了这一点。

有很多例子,英特尔在 SDM 手册和许多其他文档中明确指出,共享结构的设计是为了保证公平性,这是比最小前进进度更强大的受让人。 (出于性能或其他原因,这可能并不总是准确的,因为某些类型的请求可能总是具有更高或最高的优先级。也许更好的说法是通常保证公平性并且总体上保证前进,或者类似的东西。)这些例子包括以下内容(来自我的脑海):

  • 在 Nehalem 之前的多核处理器和多核 Atom 品牌处理器上,L2 超级队列(包括 L2 控制器)被设计为(通常)公平,并保证与其交互的所有代理的进度。
  • 前端总线(在具有 FSB 的系统上)和 APIC 总线(在具有单独 APIC 总线的系统上)都被设计为公平的。
  • 同一内核上的硬件线程之间的大多数仲裁点都被设计为公平的。一个例外是具有统一 RS 的微架构上的 uop 调度程序,或者具有分布式 RS 的微架构上的 uop 调度程序,它们使用先就绪伪 FIFO 算法。
  • 在使用交叉互连的处理器上,L3 全局队列的公平性得到保证。
  • 在具有环互连的处理器上,在某些环停止处保证公平性,而在其他环停止处仅保证前进进度。

因此,如果两个核心尝试获取对同一位置的原子 RMW 访问,则保证原子指令能够通过每个核心的管道和内存层次结构,并且每个核心的读锁定请求最终将轮到得到服务。所以,是的,根据上面的定义,x86 是免等待的。但值得注意的是,大多数或所有英特尔处理器都很少出现导致所有或部分处理器无限期挂起的错误。

一个有趣的考虑是,是否可以保证核心的进程不会因连续处理中断而无限期地受阻。我认为这主要取决于中断处理程序的设计,因此系统软件必须保证这一点。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

X86 原子 RMW 指令是否空闲等待 的相关文章

  • Polygot 包含 nasm/yasm 和 C 的文件

    我有一堆幻数 我想将它们包含在由 nasm 或 yasm 编译的 C 程序和汇编文件中 在纯 C 语言中 该文件看起来像是一系列定义 例如 define BLESS 55378008 define ANSWER 42 在 nasm 或 ya
  • 与 GNU Make 等 Python 相关的并行任务并发

    我正在寻找一种方法或者可能是一种哲学方法来如何在 python 中执行类似 GNU Make 的操作 目前 我们使用 makefile 来执行处理 因为 makefile 非常擅长通过更改单个选项 j x 进行并行运行 此外 gnu mak
  • Python 多处理:全局对象未正确复制到子级

    前几天我回答了一个关于SO的问题 https stackoverflow com q 67047533 1925388关于并行读取 tar 文件 这是问题的要点 import bz2 import tarfile from multipro
  • 将 XMM 寄存器压入堆栈

    有没有办法将打包双字整数从 XMM 寄存器推送到堆栈 然后在需要时将其弹出 理想情况下 我正在寻找通用寄存器的 PUSH 或 POP 之类的东西 我已经检查了英特尔手册 但我要么错过了命令 要么没有 或者我是否必须将值解压到通用寄存器然后推
  • 如何让BackgroundWorker返回一个对象

    我需要做RunWorkerAsync 返回一个List
  • ArrayDeque 和 LinkedBlockingDeque

    只是想知道为什么他们做了一个LinkedBlockingDeque而同一个非并发对应物是ArrayDeque它基于可调整大小的数组 LinkedBlockingQueue使用一组节点 例如LinkedList 尽管没有实施List 我知道可
  • 为什么 ATOMIC_FLAG_INIT 为假?

    In C 11有std atomic flag这对于线程循环很有用 static std atomic flag s done ATOMIC FLAG INIT void ThreadMain while s done test and s
  • 无论线程如何,对象是否总是能看到其最新的内部状态?

    假设我有一个带有简单整数计数变量的可运行对象 每次可运行对象运行时该变量都会递增 该对象的一个 实例被提交以在计划的执行程序服务中定期运行 class Counter implements Runnable private int coun
  • 获取 Future 对象的进度的能力

    参考 java util concurrent 包和 Future 接口 我注意到 除非我弄错了 只有 SwingWorker 实现类才能启动冗长的任务并能够查询进度 这就引出了以下问题 有没有办法在非 GUI 非 Swing 应用程序 映
  • 在Linux中修改子进程的全局变量

    我有 C 背景 在 C 并发方面遇到了一些困难 我不会对你撒谎 这是我必须为学校做的一个项目的一部分 虽然在专业上我曾使用过高级语言 但我的高级论文教授强迫全班同学使用 C 语言编写代码 我们大多数人几乎没有这方面的经验 从而让我们陷入了困
  • 如何阅读英特尔操作码符号

    我正在阅读一些引用的材料Intel vol 2 SDM x86 手册 https www intel com content www us en developer articles technical intel sdm html关于汇编
  • 如何使用固定数量的工作线程实现简单线程

    我正在寻找最简单 最直接的方法来实现以下内容 主程序实例化worker 执行任务的线程 Only n任务可以同时运行 When n已达到 不再有工人 开始直到计数 正在运行的线程回落到下方n 我觉得Executors newFixedThr
  • 为什么 VC++ 编译器 MOV+PUSH args 而不是仅仅 PUSH 它们? x86

    在 VC 的反汇编中 正在进行函数调用 编译器在压入本地指针之前将其 MOV 到寄存器 memcpy nodeNewLocation pNode sizeCurrentNode 0041A5DA 8B 45 F8 mov eax dword
  • 为什么将 char 传递给函数会改变它在 c 中的值?

    我目前正在关注本作业簿 http www cs bham ac uk exr lectures opsys 10 11 lectures os dev pdf关于构建操作系统 我的目的是写一个64位内核 我已经在文本模式下加载 内核 代码并
  • Java 中的 64 位赋值在 32 位机器上是原子的吗?

    如果我有这样的代码 long x x 0xFFFFFFFFL 如果我在 32 位机器上运行此代码 它是否保证是原子的 或者读取 x 的不同线程是否可能获得不完整 垃圾值 这是简短的摘要 作为参考 读 写是ALWAYS原子 即使在 64 位实
  • Goroutine 是如何工作的? (或者:goroutines 和操作系统线程的关系)

    其他 goroutine 如何在调用系统调用时继续执行 当使用 GOMAXPROCS 1 时 据我所知 当调用系统调用时 线程会放弃控制权 直到系统调用返回 Go 如何在不为每个阻塞系统调用 goroutine 创建系统线程的情况下实现这种
  • Intel 和 AMD 处理器有相同的汇编程序吗?

    C语言被用来编写Unix以实现可移植性 使用不同编译器编译的同一个C语言程序会产生不同的机器指令 为什么 Windows 操作系统能够在两者上运行Intel https en wikipedia org wiki Intel and AMD
  • 如何使用 LOCK ASM 前缀来读取值?

    我知道如何使用 LOCK 来线程安全地递增一个值 lock inc J 但是如何以线程安全的方式读取 J 或任何值 LOCK 前缀不能与 mov 一起使用 如果我执行以下操作 xor eax eax lock add eax J mov J
  • 竞争条件和 Clojure Atoms

    clojure atom 的文档指出 Changes to atoms are always free of race conditions 然而 竞争条件不仅是根据更改定义的 而且是在不同线程中并行逻辑操作的上下文中定义的 我想知道 保证
  • 对原子变量的非原子操作,反之亦然[重复]

    这个问题在这里已经有答案了 给出以下代码 static int x static void f for int i 0 i lt 100 i atomic fetch add x 3 进一步 假设f由两个线程同时调用 C C 内存模型是否保

随机推荐

  • jQuery 上的 trigger('click') 和 click() 有什么区别

    我正在寻找这两者之间的性能差异 我在 SSE 中找不到关于这个主题的好的答案 一些例子会有很大帮助 如果你查看 jQuery 代码 你会发现所有click does 是执行trigger click jQuery each blur foc
  • 使用 scala 和 GAE 玩框架

    有谁知道如何让 Play 框架的 scala 版本在 Google App Engine 中运行 此时我只是尝试让默认应用程序运行 我正在使用带有 gae 1 4 和 scala 0 9 1 模块的 Play 1 2 2 我创建了一个默认应
  • 如何在特征值中转置张量

    我试图获得两个张量的矩阵乘积 其中一个张量应该在相乘之前转置 At B 到目前为止我发现的是没有任何转置和两个矩阵转置的矩阵乘积 我正在寻找一种方法 可以直接收缩两个张量并转置其中一个张量 或者在收缩一个张量之前转置一个张量 我发现 转置效
  • 使用 C# 通过数据库中存储的文件路径在 Crystal Reports 10 中显示图像

    我有一个 C Windows 应用程序 它将员工数据存储到 MYSQL 数据库中 包括他们的图片文件路径 192 168 13 6 IDPictures Unknown jpg 有人可以帮助我如何通过从数据库读取文件路径来显示 Crysta
  • php preg_replace 匹配字符串但仅替换其中的一部分

    我有这样的文字 Retailer ul Amazon foloseste metode severe pentru a si descuraja etc angajatii din depozite sa nu mai fure din p
  • 使用 SELECT 结果作为其他 SELECT 中的 COLUMN 名称

    是否可以使用选择的结果作为字符串与其他选择中列名中的另一个字符串连接 Example SELECT brand FROM articles a WHERE a id 12345678 结果 BRAND A 我现在想要连接 PRICE to
  • 如何使用 LoadImage 和 StretchDIBits 绘制 PNG 图像?

    这与问题有关如何使用 Win32 GDI 加载 PNG 图像 如果可能 不要使用 GDI https stackoverflow com questions 4567875 how would i load a png image usin
  • 从 PyQt GUI 类外部访问 GUI 元素 text( )

    Ui MainWindow 是由设计器和 pyuic 生成的 py 文件 我想将 PyQt GUI 元素文本值传递到另一个文件并执行一些基本操作并返回结果 父文件 from PyQt4 import QtCore QtGui try fro
  • 将 SQL 查询替换为 LINQ 查询

    我有SQL检查今天的查询 根据表中存储 3 个字母字符的字段进行检查 如下所示 如果今天是星期二我需要归还记录 我有这样的 SQL 查询 SELECT TOP 1 EndTime StartTime OrderDay FROM dbo Se
  • .NET 4.6 之前的 Buffer.MemoryCopy 的替代方案

    我正在尝试将一些 NET 4 6 代码降级到 NET 4 5 这是我目前正在使用的代码块 fixed byte destination dataBytes Buffer MemoryCopy data destination dataLen
  • 为什么 JavaMail Transport.send() 是静态方法?

    我正在修改我没有编写的使用 JavaMail 的代码 并且在理解为什么 JavaMail API 是这样设计的方面遇到了一些困难 我有一种感觉 如果我理解的话 我可以做得更好 We call transport session getTra
  • Java使用String.format进行十进制格式化?

    我需要将十进制值格式化为字符串 其中我始终显示至少 2 位小数 最多 4 位小数 例如 34 49596 would be 34 4959 49 3 would be 49 30 可以使用 String format 命令来完成此操作吗 或
  • 如何在 yocto 中打补丁?

    我正在尝试使用 yocto poky warrior 和 meta tegra Warriors l4t r32 2 层为 jetson nano 构建图像 我一直在关注这个线程 https stackoverflow com questi
  • T4 vs CodeDom vs Oslo [已关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 连接集合返回函数 (SRF) 并访问 SQLAlchemy 中的列

    假设我有一个activity表和一个subscription桌子 每个活动都有一个对其他对象的通用引用的数组 每个订阅都有一个对同一集中的其他对象的通用引用 CREATE TABLE activity id serial primary k
  • 检查特定的exe文件是否正在运行

    我想知道如何检查特定位置的程序是否正在运行 例如 test exe 有两个位置 c loc1 test exe 和 c loc2 test exe 我只想知道 c loc1 test exe 是否正在运行 而不是 test exe 的所有实
  • 如何动态改变datagrid行的背景颜色?

    似乎有各种黑客可以改变数据网格行的背景颜色 但所有这些似乎都发生在渲染时 See 在 Adob e Flex 中设置数据网格行的背景颜色 https stackoverflow com questions 748213 setting ba
  • Sql:将行转变成列

    考虑下面的例子 我有一个Person包含人员记录和人物属性包含链接到人员的可选属性的表 表 人 ID Name 1 Joe Bloggs 2 Jane Doe 表人员属性 PersonId Key Value 1 Age 27 2 Hair
  • 是 C++ 语句“delete [] Q;”的 Big-O O(1) 还是 O(n)?

    标题是不言自明的 很简单的问题 我认为这是 O n 但想在明天的期末考试之前验证一下 简短的回答是 这取决于情况 If Q是一个指向具有析构函数的对象数组的指针 那么delete Q将需要调用所有这些析构函数 这将调用 O n 析构函数 其
  • X86 原子 RMW 指令是否空闲等待

    在 x86 上 原子 RMW 指令如lock add dword rdi 1在现代 CPU 上使用高速缓存锁定来实现 因此 高速缓存行在指令执行期间被锁定 这是通过在读取值时获取行 EXCLUSIVE MODIFIED 状态来完成的 并且