首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >x86_64和ARM上的原子CAS操作总是使用std::memory_order_seq_cst吗?

x86_64和ARM上的原子CAS操作总是使用std::memory_order_seq_cst吗?
EN

Stack Overflow用户
提问于 2013-09-02 16:38:25
回答 3查看 3K关注 0票数 4

As 安东尼·威廉姆斯说

some_atomic.load(std::memory_order_acquire)只是简单的加载指令,而some_atomic.store(std::memory_order_release)则是简单的存储指令。

众所周知,在x86的操作中,load()store()内存屏障memory_order_consume, memory_order_acquire, memory_order_release, memory_order_acq_rel不需要处理器指令。

但是在ARMv8上,我们知道对于load()store()http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2 http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2都有内存屏障

关于CPU的不同体系结构:http://g.oswego.edu/dl/jmm/cookbook.html

其次,对于x86上的CAS操作,在反汇编代码(MSVS2012 x86_64)中,具有不同内存屏障的这两行是相同的:

代码语言:javascript
复制
    a.compare_exchange_weak(temp, 4, std::memory_order_seq_cst, std::memory_order_seq_cst);
000000013FE71A2D  mov         ebx,dword ptr [temp]  
000000013FE71A31  mov         eax,ebx  
000000013FE71A33  mov         ecx,4  
000000013FE71A38  lock cmpxchg dword ptr [temp],ecx  

    a.compare_exchange_weak(temp, 5, std::memory_order_relaxed, std::memory_order_relaxed);
000000013FE71A4D  mov         ecx,5  
000000013FE71A52  mov         eax,ebx  
000000013FE71A54  lock cmpxchg dword ptr [temp],ecx  

GCC 4.8.1 x86_64 - GDB编写的反汇编代码

代码语言:javascript
复制
a.compare_exchange_weak(temp, 4, std::memory_order_seq_cst, std::memory_order_seq_cst);
a.compare_exchange_weak(temp, 5, std::memory_order_relaxed, std::memory_order_relaxed);

0x4613b7  <+0x0027>         mov    0x2c(%rsp),%eax
0x4613bb  <+0x002b>         mov    $0x4,%edx
0x4613c0  <+0x0030>         lock cmpxchg %edx,0x20(%rsp)
0x4613c6  <+0x0036>         mov    %eax,0x2c(%rsp)
0x4613ca  <+0x003a>         lock cmpxchg %edx,0x20(%rsp)

是任何原子CAS操作的x86/x86_64平台上,像这个atomic_val.compare_exchange_weak(temp, 1, std::memory_order_relaxed, std::memory_order_relaxed);这样的示例总是满足于排序std::memory_order_seq_cst

如果x86上的任何CAS操作总是以顺序一致性(std::memory_order_seq_cst)运行,而不考虑障碍,那么在ARMv8上也是一样的吗?

问题:CASstd::memory_order_relaxed顺序应该在x86或ARM上阻塞内存总线吗?

compare_exchange_weak()回答:使用任何std::memory_orders(偶数std::memory_order_relaxed) On x86操作总是转换为std::memory_orders 有了锁总线,才是真正的原子,并且与XCHG - 指令“具有相等的开销。

(添加:XCHG等于LOCK XCHG,但CMPXCHG不等于LOCK CMPXCHG(实际上是原子的)

ARM和PowerPC for any`compare_exchange_weak()中,是不同的锁处理器指令(通过LL/SC )。

处理器存储器.屏障.x86(非化学文摘社)、ARM和PowerPC的说明:http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-09-03 05:46:53

您不应该担心编译器将给定的C11构造映射到哪些指令,因为这并不能捕获所有内容。相反,您需要开发有关C11内存模型的保证的代码。如上所述,您的编译器或未来的编译器可以自由地重新排序轻松的内存操作,只要它不违反C11内存模型。通过像CDSChecker这样的工具运行代码也是值得的,以查看在内存模型下允许哪些行为。

票数 5
EN

Stack Overflow用户

发布于 2013-09-03 05:05:04

x86保证加载后的负载是有序的,存储是按顺序排列的。考虑到CAS需要加载和存储,所有操作都必须围绕它进行排序。

但是,值得注意的是,在存在带有memory_order_relaxed的多个atomics的情况下,编译器可以重新排序它们。它不能用memory_order_seq_cst做到这一点。

票数 2
EN

Stack Overflow用户

发布于 2015-09-04 08:00:25

我认为编译器会发出lock cmpxchg,即使对于memory_order_relaxed也是如此,因为这是确保compare+exchange本身实际上是原子的唯一方法。正如artless_noise在评论中所说的,其他体系结构可以使用加载链接/存储条件来实现compare_exchange_weak(...)

memory_order_relaxed仍然应该让编译器从循环中提升其他变量的存储,否则在编译时重新排序内存访问。

如果有一种方法可以在x86上实现,而这也不是一个完整的内存屏障,那么一个好的编译器就会将它用于memory_order_relaxed

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

https://stackoverflow.com/questions/18577584

复制
相关文章

相似问题

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