我对在应用程序中使用std::atomic<float>
与普通float
的性能感到好奇。我也对影响这一点感到好奇。我经常看到关于原子与互斥量的性能的话题,但是我发现很难找到有关原子与非原子的信息。
我不是想以此作为选择使我的代码是否线程安全的方法,只是想了解所涉及的开销。
(编辑:在原始问题的这一点上,我给出了一个示例(请参见下文),该示例应被用来说明实现的更改,而不是询问有关该代码的特定问题。这似乎使人们感到困惑。关于我在问什么,所以我把它拿出来了。)
我基本上想知道影响std :: atomic性能的主要因素是什么。是平台吗?它们的使用方式?使用两个线程访问的原子量大致相等,而不是使用一个线程95%的时间访问它们而另一个线程只是偶尔访问一个原子,会更慢吗?
在这方面,std::atomic<int>
和std::atomic<float>
之间有什么区别吗?
预先感谢
亚当
原始问题示例:
基本上,我尝试制作一百万个浮点并将值写入200次。我花了0.87秒。将它们更改为 std::atomic<float>
后,大约需要2.5秒。因此,这意味着使用std::atomic<float>
的费用大约是其三倍。
我尝试了此操作,但是读取的是值而不是写入的值,结果发现正常的 float
和std::atomic<float>
花费相同的时间。
但这受其他因素影响吗?如果另一个线程正在写/读我的原子,这是否会减慢其他对同一变量的读/写速度?大概是这样,但是我该如何更好地理解呢?
答案 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之间有什么区别吗?
假设两者都是无锁的,可能不是。排序约束是导致性能下降的原因。