C++ std::原子变量与非原子变量的性能如何?

C++ std::原子变量与非原子变量的性能如何?,c++,multithreading,performance,thread-safety,atomic,C++,Multithreading,Performance,Thread Safety,Atomic,我很好奇在应用程序中使用std::atomic与普通float相比的性能。我也很好奇是什么影响了这一点。我经常看到关于原子与互斥体性能的主题,但我发现很难找到原子与非原子的信息 我并不是将此作为选择代码线程安全与否的一种方式,只是想了解所涉及的开销 (编辑:在原始问题的这一点上,我给出了一个示例(见下文),该示例旨在说明实现的更改,而不是询问有关该代码的特定问题。这似乎让人们对我的问题感到困惑,因此我将其删除。) 我主要想知道影响std::atomic性能的主要因素是什么。是月台吗?他们的使用方

我很好奇在应用程序中使用
std::atomic
与普通
float
相比的性能。我也很好奇是什么影响了这一点。我经常看到关于原子与互斥体性能的主题,但我发现很难找到原子与非原子的信息

我并不是将此作为选择代码线程安全与否的一种方式,只是想了解所涉及的开销

(编辑:在原始问题的这一点上,我给出了一个示例(见下文),该示例旨在说明实现的更改,而不是询问有关该代码的特定问题。这似乎让人们对我的问题感到困惑,因此我将其删除。)

我主要想知道影响std::atomic性能的主要因素是什么。是月台吗?他们的使用方式?如果两个线程访问原子的数量大致相同,而一个线程95%的时间访问原子,而另一个线程只是偶尔访问原子,那么使用原子的速度会慢吗

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

提前感谢,

亚当


原始问题的示例:

基本上,我试着制作一百万个浮动并将值写入其中200次。这花了我0.87秒。一旦我将它们更改为
std::atomic
,这大约需要2.5秒。因此,这意味着使用
std::atomic
的成本大约是原来的3倍

我尝试了这个方法,但目的是读取值而不是写入值,结果发现正常的
浮点
std::atomic
花费的时间相同


但这是否受到其他因素的影响?如果另一个线程正在写入/读取我的atomics,这是否会降低对同一变量的其他读取/写入速度?大概是这样,但我如何才能更好地理解这一点呢?

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

atomic<float> f;
f.store(3.14);
这将消除
mfence
,并可能显示出显著的性能差异。在某些平台上,它甚至比非原子存储更接近

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


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

您需要编写测试。我们需要查看测试、结果和编译选项。哦,这可能也是特定于平台/工具链的。另请参见:AFAIK,这高度依赖于平台。即使在一个平台上,它也可能因您使用或滥用它们的方式而发生巨大变化。您为什么关心性能如何<代码>标准::原子应用于提供线程之间的同步。如果需要
std::atomic
来防止数据竞争,那么就使用它。如果您不需要阻止数据竞争,那么只需使用
浮点
。如果您正朝着我相信的方向前进,那么您是对的。同步线程的成本很容易超过线程的好处。不幸的是,任何人告诉你这是不是真的,唯一的办法是逐案处理。我的经验是写一个最容易得到正确的,维护和配置文件。如果结果不符合标准,请尝试其他方法。如果结果足够好,如果另一个更快,谁会给蓝精灵一个呢?原子变量比非原子变量慢得多。但是多少钱?这取决于具体的条件(CPU、争用-争用非常重要,等等)。所以说真的,你需要尝试一下。如果它们表现不好,那么您需要尝试其他解决方案。(只是一些数据:正如我记得的——我几年前做过这个测试——如果没有争用,增加一个原子int会慢25倍。如果有高争用,则慢100倍以上)。如果没有争用,就没有理由使用原子int。如果存在争用,则不能将原子与非原子进行比较,因为非原子不起作用。因此,“性能”的比较是毫无意义的。这在单个实例中是正确的-但在更大的应用程序中,您可以选择多线程和单线程解决方案,了解与多线程工具相关的开销可以让您确定哪种方法是最好的。@stark:如果您想过河,你得坐船去。如果你想在路上旅行,你需要开车。因此,对它们的速度进行比较是毫无意义的。例如,思考原子经济学的成本,以推断算法是否值得并行,是完全合理的。但我想更容易表现得高高在上,告诉OP为什么他的问题(据说)是荒谬的。可悲的是,这在当今社会太普遍了。当然,问一下原子指令的性能含义是什么是有意义的。
0x00000000004006d0 <+0>:     movl   $0x4048f5c3,0x20096a(%rip)        # 0x601044 <f>
0x00000000004006da <+10>:    mfence
f.store(3.14, std::memory_order_relaxed);