收购/释放与顺序一致性内存顺序(Acquire/Release versus Sequentiall

2019-07-19 20:16发布

对于任何std::atomic<T>其中T是一个基本类型:

如果我使用std::memory_order_acq_relfetch_xxx操作,并且std::memory_order_acquireload运行std::memory_order_releasestore经营一味(我的意思是,就像重置这些功能的默认内存排序)

  • 请问结果是一样的,如果我使用std::memory_order_seq_cst (正在使用默认)任何声明的操作?
  • 如果结果是一样的,就是这个用法比使用无论如何不同std::memory_order_seq_cst在效率方面?

Answer 1:

在C ++为原子操作11存储器排序参数指定所述排序约束。 如果你做一个店std::memory_order_release ,并从另一个线程的负载读取与价值std::memory_order_acquire从第二个线程则后续读取操作将通过在此之前,是第一个线程看到存储到任何存储位置的任何值商店释放, 或更高存储于任何那些存储器位置

如果同时存储和后续的加载是std::memory_order_seq_cst那么这两个线程之间的关系是相同的。 你需要更多的线程看出区别。

例如std::atomic<int>变量xy ,无论最初为0。

主题1:

x.store(1,std::memory_order_release);

主题2:

y.store(1,std::memory_order_release);

主题3:

int a=x.load(std::memory_order_acquire); // x before y
int b=y.load(std::memory_order_acquire); 

主题4:

int c=y.load(std::memory_order_acquire); // y before x
int d=x.load(std::memory_order_acquire);

由于写入,有商店之间没有关系xy ,所以它是非常有可能看到a==1b==0在螺纹3,以及c==1d==0在螺纹4。

如果所有的内存排序更改为std::memory_order_seq_cst那么这可以确保对存储之间的排序xy 。 因此,如果线3看到a==1b==0则意味着商店x必须是商店之前y ,因此,如果线4看到c==1 ,这意味着商店y已完成,则商店x也必须完成,所以我们必须要有d==1

在实践中,然后使用std::memory_order_seq_cst到处都将增加额外的开销,要么加载或存储或两者兼而有之,这取决于你的编译器和处理器架构。 例如,用于x86处理器的常用技术是使用XCHG指令,而不是MOV指令std::memory_order_seq_cst店,以提供必要的排序保证,而对于std::memory_order_release普通MOV就足够了。 在有更宽松的内存架构的系统开销可能更大,因为普通的加载和存储有较少的保证。

内存排序是困难的。 我专门几乎一整章给它我的书 。



Answer 2:

内存排序可能是相当棘手,而且犯错的效果往往是非常微妙的。

与所有的存储排序,关键的一点是,它保证什么“已经发生”,没有什么事情发生。 例如,如果你存储东西几个变量(例如x = 7; y = 11;则另一处理器可以能够看到y为11它看到前值7 x中。 通过使用设定之间存储器排序操作x和设置y ,所使用的处理器将保证x = 7; 已被写入到内存继续储存的东西之前y

大多数时候,它不是真正重要的什么顺序写的发生,只要价值最终更新。 但是,如果我们,比如说,有整数的循环缓冲区,我们这样做:

buffer[index] = 32;
index = (index + 1)  % buffersize; 

和一些其他的线程使用index来确定新的值写入,那么我们就需要有32先写,然后index后进行更新。 否则,其他线程可能会old数据。

这同样适用于制作的旗语,互斥这类东西的工作 - 这就是为什么条款发布和获取用于记忆障碍的类型。

现在, cst是最严格的排序规则-它强制执行读取和编写了数据的写入出去内存处理器才可以继续做多操作。 这将是比做具体的获取或释放障碍慢。 它迫使处理器,以确保存储和加载已经完成,而不是仅仅商店或只是负载。

多大区别呢,让? 它是高度依赖于系统archiecture是什么。 在一些系统上,高速缓存需要刷新[部分],并从一个核心到另一个送往说:“如果你想继续请做这个缓存刷新工作”中断 - 这可能需要几百个周期。 在其他处理器,这只是一些很小的比例高于做一个普通的内存写入速度较慢。 X86是快速做这相当不错。 某些类型的嵌入式处理器,(某些型号 - ?不知道)ARM例如,需要更多的工作,在处理器,以确保一切正常。



文章来源: Acquire/Release versus Sequentially Consistent memory order