首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >编译器重新排序与内存重新排序

编译器重新排序与内存重新排序
EN

Stack Overflow用户
提问于 2014-12-14 17:30:09
回答 1查看 2K关注 0票数 2

在gcc的指导下,可以使用以下指令来设置内存屏障。它们都提供不同的“保护”

代码语言:javascript
运行
复制
asm volatile("" ::: "memory"); // compiler reorder
asm volatile("mfence" ::: "memory"); // memory reordering

简单地说,C++原子提供:

代码语言:javascript
运行
复制
- acquire/release semantics
- Sequentially-consistent ordering

我想知道gcc原语和C++原子语义之间是否存在直接映射?(例如,(这肯定是错误的,只是为了解释目的),获取/发布语义是为了防止编译器重新排序,顺序一致的排序是为了防止内存重新排序)

或者C++没有做这个区别?该语言只提供语义,这适用于两个重新排序在同一时间?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-12-14 18:37:26

第一个障碍只适用于编译过程。编译器完成后,不会产生任何影响,因为代码中没有添加任何内容。这可能有助于避免某些内存排序问题(编译器不知道其他线程如何操作这些内存位置,尽管几乎所有具有正常设置的编译器都不敢重新排序具有此功能的变量)。

然而,这还远远不够,因为在现代的无序CPU上,硬件本身可能会重新排序下的操作。为了避免这种情况,您可以告诉HW注意,考虑到您希望达到的限制的确切级别和形式(顺序一致性是最严格和“安全”的排序模型,但在性能方面通常也是最昂贵的)。

要实现这些限制,您可以尝试手动维护屏障和ISA提供的类似构造(通过本质、内联程序集、序列化操作或任何其他技巧)。即使您知道自己在做什么,这通常也很复杂,甚至可能是特定于微体系结构的(一些CPU可能会“免费”授予一些限制,使显式围栏变得毫无用处),因此c++11添加了原子语义来简化这项任务,现在编译器根据所需的指定排序模型为您添加必要的代码。

在您的示例中,mfence是手动操作的示例,但您还需要知道在哪里应用它。如果正确使用,mfence可以是足以提供seq一致性的字符串,但也非常昂贵,因为它包括了一个商店围栏(mfence = sfence + lfence),它需要从内部缓冲区中耗尽所有挂起的存储,这是一个缓慢的操作,因为缓冲是为了允许他们延迟提交。另一方面,如果您想获取/发布语义,您可以选择在考虑到您的体系结构的正确位置上使用适当的部分栅栏来实现它们,或者让编译器为您实现它们。例如,如果您选择后者并在x86机器上运行,您将发现大多数情况下不需要添加任何内容,因为存储具有隐式发布语义,而loads具有获取语义,但在其他体系结构中可能不存在相同的情况。

以下是每个体系结构的各种排序语义实现的一个很好的总结-- http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27471969

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档