x86架构的内存排序限制

inf*_*inf 2 c++ architecture multithreading memory-model c++11

在他的伟大着作"C++并发行动"中,Anthony Williams撰写了以下内容(第309页):

例如,在x86和x86-64架构,原子加载操作总是相同的,无论是标记为memory_order_relaxed或memory_order_seq_cst(见第5.3.3节).这意味着使用松散内存排序可在与x86架构,它会在系统上会失败,并finer-晶组内存排序指令,如SPARC系统的工作编写的代码.

我是否认为在x86架构中所有原子加载操作都是正确的memory_order_seq_cst?另外,在cppreference std::memory_order网站上提到在x86发布 - 获取顺序是自动的.

如果此限制有效,那么排序是否仍适用于编译器优化?

Pao*_*ini 5

是的,排序仍然适用于编译器优化.

而且,在x86上"原子加载操作总是相同的"并不完全准确.

在x86上,完成的所有加载mov都具有获取语义,并且所有完成的存储mov都具有释放语义.所以acq_rel,acq和轻松加载都很简单mov,类似的acq_rel,rel和relax存储(acq存储和rel加载总是等于放松).

然而,这不是seq_cst不一定是真的:架构并不能保证seq_cst语义mov.实际上,x86指令集没有任何针对顺序一致的加载和存储的特定指令.只有x86上的原子读 - 修改 - 写操作才具有seq_cst语义.因此,您可以通过执行lock xadd带参数0的fetch_and_add操作(xchg指令)和通过执行seq_cst交换操作(指令)并丢弃先前值的存储的seq_cst语义来获取负载的seq_cst语义.

但你不需要两者兼顾!只要所有seq_cst存储都完成xchg,seq_cst加载就可以简单地用a实现mov.双重地,如果所有负载都完成了lock xadd,seq_cst存储可以简单地用a实现mov.

xchg并且lock xadd比...慢得多mov.因为程序(通常)比商店有更多的负载,所以seq_cst存储很方便,xchg因此(更频繁的)seq_cst加载可以简单地使用a mov.此实现细节在x86应用程序二进制接口(ABI)中编写.在x86上,兼容的编译器必须编译seq_cst存储,xchg以便可以使用更快的mov指令来加载seq_cst(可能出现在另一个转换单元中,使用不同的编译器编译).

因此,通常不会在x86上使用相同的指令完成seq_cst和获取加载.这是唯一的,因为ABI指定将seq_cst存储编译为xchg.