fetch_add(0, memory_order_relaxed/release) 到 mfence + mov 的转换合法吗?

2023-11-21

论文N4455 没有健全的编译器会优化原子讨论编译器可以应用于原子的各种优化。在该部分下围绕原子进行优化,对于 seqlock 示例,它提到了在 LLVM 中实现的转换,其中fetch_add(0, std::memory_order_release)变成了mfence接下来是普通负载,而不是通常的负载lock add or xadd。这个想法是,这避免了对缓存行的独占访问,并且相对便宜。这mfence无论提供的排序约束如何,仍然需要防止StoreLoad重新排序为mov指令生成。

This 转型是为这样的执行read-don't-modify-write无论订购如何操作,都会生成等效的组件fetch_add(0, memory_order_relaxed).

不过,我想知道这是否合法。 C++ 标准明确指出[原子顺序] that:

原子读-修改-写操作应始终读取在与读-修改-写操作关联的写操作之前写入的最后一个值(按修改顺序)。

关于 RMW 操作看到“最新”值的事实也已被注意到之前作者:安东尼·威廉姆斯。

我的问题是:基于原子变量的修改顺序、基于编译器是否发出lock add vs mfence接下来是普通负载?此转换是否有可能导致执行 RMW 操作的线程改为加载早于最新值的值?这是否违反了 C++ 内存模型的保证?


(我不久前开始写这篇文章,但陷入了停滞;我不确定它是否能构成完整的答案,但我认为其中一些内容可能值得发布。我认为@LWimsey 的评论可以更好地抓住问题的核心比我写的答案。)

是的,很安全。

请记住,as-if 规则的应用方式是,真实机器上的执行必须始终生成与 C++ 抽象机上可能的执行相匹配的结果。对于优化来说,在目标上进行 C++ 抽象机允许不可能执行的某些执行是合法的。例如,即使是针对 x86 进行编译,也无法进行所有 IRIW 重新排序,无论编译器是否喜欢。 (见下文;某些 PowerPC 硬件是唯一可以在实践中做到这一点的主流硬件。)


我认为专门针对 RMW 的措辞的原因是它将负载与 ISO C++ 要求每个原子对象单独存在的“修改顺序”联系起来。 (或许。)

Remember that the way C++ formally defines its ordering model is in terms of synchronizes-with, and existence of a modification order for each object (that all threads can agree on). Not like hardware where there is a notion of coherent caches1 creating a single coherent view of memory that each core accesses. The existence of coherent shared memory (typically using MESI to maintain coherence at all times) makes a bunch of things implicit, like the impossibility of reading "stale" values. (Although HW memory models do typically document it explicitly like C++ does).

因此,转变是安全的。

ISO C++ 在另一节的注释中确实提到了一致性的概念:http://eel.is/c++draft/intro.races#14

由评估 B 确定的原子对象 M 的值应是由修改 M 的某些副作用 A 存储的值,其中 B 不会在 A 之前发生。
[注14:此类副作用的集合还受到此处描述的其余规则的限制,特别是受到下面的一致性要求的限制。——尾注]

...

[注19:上述四项一致性要求有效 禁止编译器将原子操作重新排序到单个对象, 即使这两个操作都是松弛负载。这有效地使得 大多数可用于 C++ 的硬件提供缓存一致性保证 原子操作。——尾注]

[注 20:原子负载观察到的值取决于 “发生在”关系之前,这取决于观察到的值 大量的原子。预期的阅读是必须存在一个 原子负载与他们观察到的修改的关联, 连同适当选择的修改顺序和“发生 如上所述导出的“之前”关系,满足所得结果 此处施加的限制。 ——尾注]

因此 ISO C++ 本身指出缓存一致性提供了一些排序,并且 x86 具有一致性缓存。 (我并没有完整地论证这是enough下单了,抱歉。 LWimsey 关于修改命令中最新的含义的评论是相关的。)

(在许多 ISA(但不是全部)上,内存模型也排除了IRIW 重新排序当您存储两个独立的对象时。 (例如,在 PowerPC 上,2 个读取器线程可能对 2 个存储到 2 个存储的顺序不一致separate对象)。很少有实现可以创建这样的重新排序:如果共享缓存是only数据在核心之间传输的方式(就像在大多数 CPU 上一样),这会创建存储顺序。)

此转换是否有可能导致执行 RMW 操作的线程改为加载早于最新值的值?

特别是在 x86 上,这很容易推理。 x86 有一个强有序记忆模型(TSO = 总存储顺序 = 程序顺序 + 具有存储转发的存储缓冲区)。

脚注 1:所有内核std::thread可以运行具有一致的缓存。对于跨所有 ISA 的所有实际 C++ 实现都是如此,而不仅仅是 x86-64。有一些异构板具有单独的 CPU 共享内存而没有缓存一致性,但同一进程的普通 C++ 线程不会在这些不同的内核上运行。看这个答案了解更多详情。

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

fetch_add(0, memory_order_relaxed/release) 到 mfence + mov 的转换合法吗? 的相关文章

  • 删除文件的最后 10 个字符

    我想删除文件的最后 10 个字符 说一个字符串 hello i am a c learner 是文件内的数据 我只是希望该文件是 hello i am a 文件的最后 10 个字符 即字符串 c learner 应在文件内消除 解决方案 将
  • 如何将 std::string& 转换为 C# 引用字符串

    我正在尝试将 C 函数转换为std string参考C 我的 API 如下所示 void GetStringDemo std string str 理想情况下 我希望在 C 中看到类似的东西 void GetStringDemoWrap r
  • 调用 McAfee 病毒扫描引擎

    我收到客户的请求 要求使用他们服务器上的 McAfee 病毒扫描将病毒扫描集成到应用程序中 我做了一些调查 发现 McScan32 dll 是主要的扫描引擎 它导出各种看起来有用的函数 我还发现提到了 McAfee Scan Engine
  • C# 异步等待澄清?

    我读了here http blog stephencleary com 2012 02 async and await html that 等待检查等待的看看它是否有already完全的 如果 可等待已经完成 那么该方法将继续 运行 同步
  • 类型中的属性名称必须是唯一的

    我正在使用 Entity Framework 5 并且有以下实体 public class User public Int32 Id get set public String Username get set public virtual
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • 如何从 Visual Studio 将视图导航到其控制器?

    问题是解决方案资源管理器上有 29 个项目 而且项目同时具有 ASP NET MVC 和 ASP NET Web 表单结构 在MVC部分中 Controller文件夹中有大约100个子文件夹 每个文件夹至少有3 4个控制器 视图完全位于不同
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • 方程“a + bx = c + dy”的积分解

    在等式中a bx c dy 所有变量都是整数 a b c and d是已知的 我如何找到整体解决方案x and y 如果我的想法是正确的 将会有无限多个解 由最小公倍数分隔b and d 但我只需要一个解决方案 我可以计算其余的 这是一个例
  • WcfSvcHost 的跨域异常

    对于另一个跨域问题 我深表歉意 我一整天都在与这个问题作斗争 现在已经到了沸腾的地步 我有一个 Silverlight 应用程序项目 SLApp1 一个用于托管 Silverlight SLApp1 Web 的 Web 项目和 WCF 项目
  • 为什么 C# 2.0 之后没有 ISO 或 ECMA 标准化?

    我已经开始学习 C 并正在寻找标准规范 但发现大于 2 0 的 C 版本并未由 ISO 或 ECMA 标准化 或者是我从 Wikipedia 收集到的 这有什么原因吗 因为编写 审查 验证 发布 处理反馈 修订 重新发布等复杂的规范文档需要
  • C# xml序列化必填字段

    我需要将一些字段标记为需要写入 XML 文件 但没有成功 我有一个包含约 30 个属性的配置类 这就是为什么我不能像这样封装所有属性 public string SomeProp get return someProp set if som
  • 复制目录下所有文件

    如何将一个目录中的所有内容复制到另一个目录而不循环遍历每个文件 你不能 两者都不Directory http msdn microsoft com en us library system io directory aspx nor Dir
  • 为什么 isnormal() 说一个值是正常的,而实际上不是?

    include
  • 编译时展开 for 循环内的模板参数?

    维基百科 here http en wikipedia org wiki Template metaprogramming Compile time code optimization 给出了 for 循环的编译时展开 我想知道我们是否可以
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • C++ 中的 include 和 using 命名空间

    用于使用cout 我需要指定两者 include
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l

随机推荐

  • 在多个集合上执行事务时,MongoDB Atlas 出错(代码 8000)

    我正在尝试从 Mongo DB Node JS 驱动程序在 Mongodb Atlas M0 实例上执行事务 如所述here 并且我收到以下错误 code 8000 codeName AtlasError errmsg internal a
  • OpenCV Python:绘制 minAreaRect (旋转矩形未实现)

    是否有任何辅助方法来绘制由返回的旋转矩形cv2 minAreaRect 大概是作为 x1 y1 x2 y2 angle cv2 矩形 不支持角度 由于返回的元组不是 RotatedRect 类 因为它似乎没有在 Python 绑定中实现 所
  • 添加多个 ClusterManager 到 Google 地图

    我正在尝试为 Google Map 使用两个 ClusterManager 但我只能添加一个 clustermanager 及其项目单击事件 googleMap setOnMarkerClickListener mClusterManage
  • TChan 写入是否已集成到 Haskell STM 中?

    如果 STM 事务失败并重试 是否会调用writeTChan重新执行 以便最终得到两次写入 或者 STM 仅在事务提交时才实际执行写入 即 这个针对睡觉理发师问题的解决方案是否有效 或者如果交易在enterShop第一次失败 import
  • 使用 CSS 浮动 DIV 之间的垂直边框

    我有以下 HTML 结构 div div Some text goes here div div Different text goes here div div class clear div div 我还有以下 CSS parent w
  • VB.Net 变量声明:键入还是不键入?

    在 VB Net 中 声明字符串的常用方法是 Dim helloWorld As String Hello World 但是 您也可以使用动态变量 例如 Dim helloWorld Hello World 两者最终都会是同一件事 但最佳实
  • 我的随机梯度下降实现正确吗?

    我正在尝试开发随机梯度下降 但我不知道它是否100 正确 我的随机梯度下降算法生成的成本有时与 FMINUC 或批量梯度下降生成的成本相差甚远 虽然当我将学习率 alpha 设置为 0 2 时 批量梯度下降成本会收敛 但我被迫将学习率 al
  • 循环phpmailer

    当我发送电子邮件时 我收到两封电子邮件 但它应该将电子邮件发送到各自的电子邮件 乱跳问题 array values Array 0 gt Array 0 gt uname1 1 gt fullname1 2 gt email 1 1 gt
  • 运行时获取DLL路径

    我想得到一个dll s其代码中的目录 或文件 路径 不是程序的 exe文件路径 我尝试了一些我发现的方法 GetCurrentDir 获取当前目录路径 GetModuleFileName 获取可执行文件的路径 那么我怎样才能找到代码在哪个d
  • 将值传递给 loadURL - Android

    是否可以将值传递给 webView loadUrl 中提到的 URL 像这样的东西 webView loadUrl file android asset www index html value value 或者有什么方法可以将 Java
  • 他们是如何做到的呢?主屏幕上的对话框

    我正在编写一个 Android 应用程序 我想在主屏幕上放置一个对话框或视图 以便用户可以输入文本而无需跳转到我的完整应用程序 我似乎无法让它发挥作用 如果我呈现一个对话框 即使在透明活动中 我的应用程序就会启动 如果您不知道我在说什么 请
  • 什么时候最适合使用 Python 中的类?

    我对 python 和一般编程都很陌生 所以非常感谢对这一点的任何澄清 例如 在以下代码中 Using a class class Monster object def init self level damage duration pri
  • 分割给定字符串并准备 case 语句

    Table 表名 create table table name given dates timestamp set name varchar 插入记录 insert into table name values 2001 01 01 20
  • 如何让 Xcode 使用 clang 的替代版本?

    我如何设置 Xcode 以使用由以下人员分发的 clangllvm org而不是苹果发货的那个 如果我下载clang 二进制文件并安装到 usr local然后将我的编译器设置为Other gt usr local bin clang在 X
  • 在需要表达式的地方放置一个大括号括起来的块的 C++ 语法是什么?

    我遇到了这个奇怪的 C 程序 include
  • 在 Eclipse Juno (4.2) 中安装 Google AppEngine 插件时出错

    当我尝试安装 GAE 的 eclipse 插件时 出现错误 无法完成安装 因为找不到一项或多项所需的项目 正在安装的软件 Google App Engine Java SDK 1 6 4 1 6 4 v201203300216r37 com
  • NHibernate 使用 AppFabric 进行二级缓存

    有人使用 AppFabric 进行二级缓存吗 我知道它遵循与 Velocity 相同的 api nhibernate caches velocity 但想知道是否有人已经有一些使用它的生产经验 以及他们是否知道任何特定的技巧或问题 我目前知
  • Node.js Express Router 中的正则表达式

    我试图找到一种方法 将正则表达式输入到快速路由 URL 中 然后通过请求对象访问 URL 的变量部分 具体来说 我想路由到网址 posts 任意数量的数字 有没有办法做到这一点 例子 posts 54 posts 2 posts 546 这
  • firebase 的“一个子值的大小”限制 10Mb 的含义

    firebase 文档指定 一个子值的大小 的限制为 10Mb 这是否意味着该子项的 JSON 对象的大小 例如 使用文档中的示例 users mchen friends brinchen true name Mary Chen our c
  • fetch_add(0, memory_order_relaxed/release) 到 mfence + mov 的转换合法吗?

    论文N4455 没有健全的编译器会优化原子讨论编译器可以应用于原子的各种优化 在该部分下围绕原子进行优化 对于 seqlock 示例 它提到了在 LLVM 中实现的转换 其中fetch add 0 std memory order rele