- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
论文 N4455 No Sane Compiler Would Optimize Atomics讨论编译器可以应用于原子的各种优化。栏目下Optimization Around Atomics ,对于 seqlock 示例,它提到了在 LLVM 中实现的转换,其中 fetch_add(0, std::memory_order_release)
变成了mfence
然后是普通负载,而不是通常的 lock add
或 xadd
.这个想法是这样避免了对缓存行的独占访问,并且相对便宜。 mfence
无论提供何种排序约束以防止 StoreLoad
仍然需要重新订购 mov
指令生成。
此 transformation对此类执行 read-don't-modify-write
无论顺序如何,都可以操作,并为 fetch_add(0, memory_order_relaxed).
生产等效的组件
但是,我想知道这是否合法。 C++ 标准在 [atomic.order] 下明确指出那:
Atomic read-modify-write operations shall always read the last value (in the modification order) written before the write associated with the read-modify-write operation.
lock add
,线程可以看到的值的行为是否存在差异?对比
mfence
其次是普通负载?这种转换是否可能导致执行 RMW 操作的线程加载比最新值更旧的值?这是否违反了 C++ 内存模型的保证?
最佳答案
(我不久前开始写这个,但停滞不前;我不确定它加起来是一个完整的答案,但我认为其中一些可能值得发布。我认为@LWimsey 的评论更能触及核心答案比我写的要好。)
是的,它很安全。
请记住,as-if 规则的适用方式是,在真实机器上的执行必须始终产生与 C++ 抽象机器上的一种可能执行相匹配的结果。优化使某些 C++ 抽象机允许在目标上不可能的执行是合法的。即使完全针对 x86 进行编译也会使所有 IRIW 重新排序成为不可能,例如,无论编译器是否喜欢它。 (见下文;一些 PowerPC 硬件是唯一可以在实践中做到这一点的主流硬件。)
我认为专门针对 RMW 的措辞的原因是它将负载与 ISO C++ 要求为每个原子对象分别存在的“修改顺序”联系起来。 (也许。)
请记住,C++ 正式定义其排序模型的方式是同步与每个对象的修改顺序的存在(所有线程都可以达成一致)。不像硬件那样有一致性缓存1的概念,创建每个内核访问的内存的单一一致 View 。连贯共享内存的存在(通常使用 MESI 始终保持连贯性)使许多事情变得隐含,例如无法读取“陈旧”值。 (尽管硬件内存模型通常像 C++ 一样明确记录它)。
因此转换是安全的。
ISO C++ 在另一部分的注释中确实提到了一致性的概念:http://eel.is/c++draft/intro.races#14
The value of an atomic object M, as determined by evaluation B, shall be the value stored by some side effect A that modifies M, where B does not happen before A.
[Note 14: The set of such side effects is also restricted by the rest of the rules described here, and in particular, by the coherence requirements below. — end note]...
[Note 19: The four preceding coherence requirements effectivelydisallow compiler reordering of atomic operations to a single object,even if both operations are relaxed loads. This effectively makes thecache coherence guarantee provided by most hardware available to C++atomic operations. — end note]
[Note 20: The value observed by a load of an atomic depends on the“happens before” relation, which depends on the values observed byloads of atomics. The intended reading is that there must exist anassociation of atomic loads with modifications they observe that,together with suitably chosen modification orders and the “happensbefore” relation derived as described above, satisfy the resultingconstraints as imposed here. — end note]
Is it possible for this transformation to cause the thread performing the RMW operation to instead load values older than the latest one?
std::thread
的所有内核可以跑过有一致的缓存。适用于所有 ISA 的所有真实 C++ 实现,而不仅仅是 x86-64。有一些具有独立 CPU 的异构板,在没有缓存一致性的情况下共享内存,但同一进程的普通 C++ 线程不会跨这些不同的内核运行。见
this answer有关更多详细信息。
关于c++ - fetch_add(0, memory_order_relaxed/release) 到 mfence + mov 的转换是否合法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64976395/
我认为我的问题与“https://serverfault.com/q/299179”和“https://serverfault.com/q/283330/71790”有些相关,但其中任何一个都没有令我
我生成了 APK 对于我的 flutter 项目和 F:\build\app\outputs\apk\release 我有 3 种类型的 apk 文件,包括 output.json 文件。他们是: *
我们最近决定更新 Beta release 的新应用程序在 Google Play 上, 现在读完指南后,我心里有一些问题,想了解更多,我用谷歌搜索进一步了解找到了一些答案,但还有一些我不确定的东西,
我正在尝试使用发布管理作为构建版本的工具,但我很难理解码件、工具和操作之间的真正区别。有人可以分解这三个概念之间的差异以及它们如何相互配合吗? 最佳答案 由于它适用于基于代理的版本: 工具旨在提供自定
我最近完成了使用 jgitflow:release-finish 合并一个发布分支来掌握和开发。 .构建成功。 但是现在我正在尝试使用 jgitflow:releast-start 创建一个新分支.但
我一直在读到,如果一个集合“被释放”,它也会释放它的所有对象。另一方面,我还读到,一旦集合被释放,集合就会释放它的对象。 但最后一件事可能并不总是发生,正如苹果所说。系统决定是否取消分配。在大多数情况
我在具有以下布局的多模块项目上使用 maven-release-plugin: ROOT/ + parent + module1 + module2 在parent的pom中,使用modu
我正在使用 ionic 构建移动应用。 我面临一个严重的问题。 我必须使用 on-touch 和 on-release 事件,但问题是每当我触摸时,on-release 甚至也会立即触发而没有实际释放
谁能解释清楚两者之间的区别是什么.Release()和->Release() 在 CComPtr 上? 确切地说,两种情况下内存管理是如何发生的? 最佳答案 CComPtr 的operator-> 函
两个片段有什么区别? [myObj release]; 和 [myObj release]; myObj = nil; 最佳答案 如果你只是释放一个对象,那么它就会变成释放对象。 如果您尝试对已释放的
我正在运行 maven 发布插件 (org.apache.maven.plugins:maven-release-plugin:2.3.2) 并注意到当通过命令行。我想知道是否有办法关闭它。 我使用
我正在尝试通过运行nuget pack -properties Configuration=Release命令来更新我的nuget软件包,但这会给我以下错误: Unable to find 'bin/
我们正在使用 Microsoft 的发布管理将我们的 Web 应用程序部署到我们的测试环境 (QA)。它是一个直接的 MVC.Net Web 应用程序。我们的构建生成一个 web 部署包,我们有一个命
我有一个在 X 环境中发布的版本 A。另一方面,我有一个在环境 Y 中发布的版本 B。 问题是我想知道我是否可以在版本 B 中检查版本 A 的状态,这样我就可以抛出错误而不发布版本 B。 我不知道是否
我正在开发一个使用大量图像的应用程序,我正在使用 UIWebView 使用 JavaScript 代码(我正在使用 UIZE 库)来表示大约 200 张图像,问题当我完成 UIWebView 时,我在
我已阅读 Marshal.GetIUnknownForObject 的文档它说: Always use Marshal.Release to decrement the reference count
为了成为 iPhone SDK 上的好内存公民,我一直在玩内存。 然而,我仍然很难理解"self.something" 和只是"something" 之间的区别。 据我了解,"self.somethi
我需要使用 bash 找出我正在运行的 Linux 发行版。找到this page ,这非常有帮助。 但是我的系统有两个/etc/*-release 文件 /etc/lsb-release /etc/
我想使用 Maven Release Plugin 将 Release Candidates 发布到我的 Nexus Snapshot 存储库。 将 RC 部署到 Nexus 不是问题,但我想利用 m
在什么情况下我们应该使用“Latch until release”而不是“Switch until release”? 根据 LabVIEW 2011 Help : Latch until relea
我是一名优秀的程序员,十分优秀!