我的应用程序需要几个原子加载和存储。不幸的是,这些操作必须在内存映射文件中的特定地址处发生,因此我不能使用c++ 11的std::atomic(因为std::atomic通过控制变量的大小和对齐/放置来工作。内存映射的文件格式,并且我们只在单个CPU架构上运行,我只是简单地查看了目标的对齐方式和大小约束,并安排了一些东西以实现原子性(在正确的位置包括完整的围栏)。

有没有一种方法(在运行时)测试对特定地址的特定大小的读取或写入是否是原子的?我的主要平台是x86-64,但我也对ARM解决方案感兴趣。

最佳答案

简短的回答:可能不是。您可以编写一些代码来更新和检查值的有效性,并将其运行6个月。但是,几乎肯定不能保证代码正确无误-只是您没有找到正确的地方来使它出错。

长答案:处理器字的加载和存储本身几乎可以肯定是原子的,但是std::atomic功能提供了更强的保证。它保证没有处理器将使用“陈旧”的值(缓存一致性和独占更新)。没有std::atomic,您将无法做出相同的保证(除非平台本身对此提供保证,这至少可能要求它成为单个核心处理器)。

在一般情况下,由处理器执行的加载和存储具有“弱”缓存一致性和原子更新策略。说我们有以下代码:

 int a = 42;
 bool flag = false;

 ...

 a++;
 flag = true;

和其他一些执行以下操作的代码:
 while(!flag)
 a--;

[我目前忽略了flag也需要原子更新策略并且可能需要可变的事实-在这种情况下,这不是重点。

不能保证编译器不会形成tmp = a; tmp = tmp+1; a = tmp;(并且对应于a--)[可能在中间插入了额外的指令以作很好的衡量,因为编译器希望以其他某种方式更快/更好]。

也不能保证该值不会被更新为43,但是其他代码在退出循环后已经读取了旧的42值,因为flag为true(因为处理器未按照您期望的顺序进行所有操作,并且缓存内容“无序更新”)。

x86处理器绝对属于无法保证如上所述更新后的值立即可用的处理器之一。缓存一致性和原子性仅保证您不会读取某些“半熟的”值-更新值时它是“旧的”或“新的”值-但在相当长的一段时间内它可能是“旧的”值写入"new"值后,通常“不是一件好事”。

关于c++ - 在运行时检测负载是否是原子的?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29222214/

10-15 17:55