我很好奇在应用程序中使用
std::atomic<float>
与普通 float
的性能。我也很好奇是什么影响了这个。我经常看到有关原子与互斥体性能的主题,但我发现很难找到有关原子与非原子的信息。
我并不是用它来选择是否使我的代码线程安全,只是想了解所涉及的开销。
(编辑:在最初的问题中,我给出了一个示例(见下文),该示例应该说明实现的更改,而不是询问有关该代码的具体问题。这似乎让人们对我的内容感到困惑问了所以我把它拿出来了。)
我基本上想知道影响 std::atomic 性能的广泛因素是什么。是平台吗?它们的使用方式?使用两个线程访问大约相同数量的原子是否比一个线程 95% 的时间访问它们而另一个线程偶尔访问原子要慢?
另外,
std::atomic<int>
和std::atomic<float>
在这方面有什么区别吗?
提前致谢,
亚当
原始问题的示例:
基本上,我尝试制作一百万个浮点并向它们写入值 200 次。这对我来说花了 0.87 秒。一旦我将它们更改为
std::atomic<float>
std::atomic<float>
。我尝试了这个,但为了读取值而不是写入,发现正常的
float
std::atomic<float>
花费相同的时间。但这会受到其他因素的影响吗?如果另一个线程正在写入/读取我的原子,这是否会减慢其他对同一变量的读取/写入速度?大概是这样,但是我怎样才能更好地理解这一点?
没有排序参数(即默认值)的原子存储非常昂贵,因为编译器会发出额外的排序指令。
在
x86
上,浮点数的默认(顺序一致)原子存储如下所示:
atomic<float> f;
f.store(3.14);
gcc
产生以下指令:
0x00000000004006d0 <+0>: movl $0x4048f5c3,0x20096a(%rip) # 0x601044 <f>
0x00000000004006da <+10>: mfence
mfence
指令很昂贵,因为它确保对其他内核的直接可见性(即导致存储缓冲区被刷新)。
您可以尝试在不订购的情况下运行测试:
f.store(3.14, std::memory_order_relaxed);
这将消除
mfence
,并且可能会显示出显着的性能差异。它在某些平台上更接近(如果不是相等的话)非原子商店。
在这方面,
和std::atomic<int>
之间有什么区别吗?std::atomic<float>
假设两者都是无锁的,可能不是。排序限制是导致性能降低的原因。