std :: atomic与non-atomic变量的性能如何?

时间:2018-08-14 17:31:50

标签: c++ multithreading performance thread-safety atomic

我对在应用程序中使用std::atomic<float>与普通float的性能感到好奇。我也对影响这一点感到好奇。我经常看到关于原子与互斥量的性能的话题,但是我发现很难找到有关原子与非原子的信息。

我不是想以此作为选择使我的代码是否线程安全的方法,只是想了解所涉及的开销。

(编辑:在原始问题的这一点上,我给出了一个示例(请参见下文),该示例应被用来说明实现的更改,而不是询问有关该代码的特定问题。这似乎使人们感到困惑。关于我在问什么,所以我把它拿出来了。)

我基本上想知道影响std :: atomic性能的主要因素是什么。是平台吗?它们的使用方式?使用两个线程访问的原子量大致相等,而不是使用一个线程95%的时间访问它们而另一个线程只是偶尔访问一个原子,会更慢吗?

在这方面,std::atomic<int>std::atomic<float>之间有什么区别吗?

预先感谢

亚当


原始问题示例:

基本上,我尝试制作一百万个浮点并将值写入200次。我花了0.87秒。将它们更改为std::atomic<float>后,大约需要2.5秒。因此,这意味着使用std::atomic<float>的费用大约是其三倍。

我尝试了此操作,但是读取的是值而不是写入的值,结果发现正常的floatstd::atomic<float>花费相同的时间。

但这受其他因素影响吗?如果另一个线程正在写/读我的原子,这是否会减慢其他对同一变量的读/写速度?大概是这样,但是我该如何更好地理解呢?

1 个答案:

答案 0 :(得分:3)

没有排序参数(即默认值)的原子存储很昂贵,因为编译器会发出其他排序指令。 在X86上,默认的(顺序一致的)原子存储为浮点型,如下所示:

atomic<float> f;
f.store(3.14);

gcc产生以下指令:

0x00000000004006d0 <+0>:     movl   $0x4048f5c3,0x20096a(%rip)        # 0x601044 <f>
0x00000000004006da <+10>:    mfence

mence指令之所以昂贵,是因为它可以确保直接看到其他内核(即导致刷新存储缓冲区的原因)。

您可以尝试运行测试而无需订购:

f.store(3.14, std::memory_order_relaxed);

这将摆脱mfence,并可能显示出明显的性能差异。如果在某些平台上不相等,它与非原子商店的距离更近。

  

在这方面,std :: atomic和std :: atomic之间有什么区别吗?

假设两者都是无锁的,可能不是。排序约束是导致性能下降的原因。