What is the performance of std::atomic vs non-atomic variables?
我对在应用程序中使用std::atomic与常规float的性能感到好奇。我也对影响这一点感到好奇。我经常看到有关原子与互斥的性能的主题,但是我发现很难找到有关原子与非原子的信息。
我不是想以此作为选择使我的代码具有线程安全性或非线程安全性的方法,只是想了解所涉及的开销。
(编辑:在原始问题的这一点上,我给出了一个示例(请参见下文),该示例应被用来说明实现的更改,而不是询问有关该代码的特定问题。这似乎使人们对我的要求感到困惑。我拿出来了。)
我基本上想知道影响std :: atomic性能的主要因素是什么。是平台吗?它们的使用方式?使用两个线程访问的原子量大致相等,而不是使用一个线程95%的时间访问它们而另一个线程只是偶尔访问一个原子,会更慢吗?
此外,在这方面std::atomic和std::atomic之间是否有区别?
提前致谢,
亚当
来自原始问题的示例:
基本上,我尝试制作一百万个浮点数并将其值写入200次。我花了0.87秒。一旦将它们更改为std::atomic,这大约需要2.5秒。因此,这意味着使用std::atomic的成本大约是其3倍。 s>
我尝试了此操作,但是读取的是值而不是写入的值,结果发现正常的float和std::atomic花费的时间相同。 s>
但这会受到其他因素的影响吗?如果另一个线程正在写/读我的原子,这是否会减慢其他对同一变量的读/写速度?大概是这样,但是我该如何更好地理解呢? s>
-
您需要编写测试。我们需要查看测试,结果和编译选项。哦,也可能是特定于平台/工具链的。另请参阅:en.cppreference.com/w/cpp/atomic/atomic/is_lock_free
-
AFAIK,这在很大程度上取决于平台。即使在一个平台上,它也可能根据您使用或滥用它们的方式而千差万别。
-
可以,但是我的测试只是为了说明我的问题,而不是问为什么特定的代码片段具有特定的结果。我要求有关原子计算成本的一些理论,而不是对我的代码的反馈
-
不同平台之间的差异可能很大。在我的平台上,std :: atomic操作所花的时间比非atomics长约40倍。
-
您为什么在乎性能呢? std::atomic应该用于在线程之间提供同步。如果您需要std::atomic来防止数据争用,请使用它。如果不需要阻止数据争用,则只需使用float。
-
在大型应用程序中,您可以有许多不同的问题解决方案,其中一种可能更简单并涉及原子,而另一些可能不涉及原子但较复杂。了解性能折衷可以帮助您决定采用哪种方法
-
SMTC-给我看代码。谈论某些未知代码在某些未知平台上的性能是没有意义的。
-
@SergeyA-没有代码,这不是关于代码不起作用或特定解决方案的问题。这是一个简单的问题-影响std :: atomic性能的因素是什么?
-
您的意思是您在使用atomic时经历了三倍的减速-向我们展示代码并提及平台。
-
@SergeyA-与问题无关。发现某些特定的平台环境或实现会影响特定的代码段,并不能回答影响std :: atomic性能的主要因素是什么。如果您不知道答案就可以了
-
如果您朝我相信的方向前进,那您是对的。同步线程的成本很容易超过线程化的好处。遗憾的是,任何人告诉您是否这样的唯一方法是根据具体情况。我的经验法则是写出最容易正确维护和配置的方法。如果结果无法消除,请尝试其他方法。如果结果足够好,如果另一个更快,谁会发出蓝精灵?
-
我不知道一个未解决的问题的答案。有数百万个原因使您的测试原子运行缓慢。简单示例-连续写入全局变量一百万次。没有atomic,它将只写入最后一个值。如果使用原子,那将是一百万封受限制的写入。有所作为,但我不会猜测您尚未显示的代码。
-
广泛的因素是:它如何在您的平台上实现,在您的平台上是否无锁以及您的平台上的内存体系结构是什么。
-
谢谢@RichardCritten :)
-
@RichardCritten,我重复一遍-基准测试代码是国王。
-
@SergeyA看到第一个评论
-
原子变量比非原子变量要慢得多。但是多少钱?这取决于确切的条件(CPU,争用-争用很重要,等等)。所以说真的,您需要尝试一下。如果他们的表现不佳,那么您需要尝试其他解决方案。 (只是一些数据:我记得-我几年前做过这个测试-如果没有争用,增加一个原子整数的速度要慢25倍。如果有高争用,则它的速度要慢100倍以上)。
-
它高度依赖于硬件。使用std::atomic会禁用优化,从而保证某些属性。您真正想要的是了解编译器和CPU进行的导致竞争条件的优化类型。令人头疼的是缓存和指令重新排序。后者可能发生在编译器,CPU和内存子系统级别。对于这两者而言,读取变量与写入变量完全不同。
没有排序参数(即默认值)的原子存储很昂贵,因为编译器会发出其他排序指令。
在X86上,默认(顺序一致)的float原子存储如下所示:
1 2
| atomic<float> f;
f.store(3.14); |
gcc产生以下指令:
1 2
| 0x00000000004006d0 <+0>: movl $0x4048f5c3,0x20096a(%rip) # 0x601044 <f>
0x00000000004006da <+10>: mfence |
mence指令非常昂贵,因为它可以确保直接看到其他内核(即导致刷新存储缓冲区的原因)。
您可以尝试运行测试而无需订购:
1
| f.store(3.14, std::memory_order_relaxed); |
这将摆脱mfence并可能显示出明显的性能差异。 如果在某些平台上不相等,那么它与非原子商店的距离更近。
is there any difference between a std::atomic and a std::atomic in this regard?
假设两者都是无锁的,可能不是。 排序约束是导致性能降低的原因。
-
如果没有争用,则没有理由使用atomic。 如果存在争用,则您无法将原子与非原子进行比较,因为非原子不起作用。 因此,"性能"的比较是没有意义的。
-
在单个实例中确实如此-但是在更大的应用程序中,您可以选择多线程和单线程解决方案,并了解与用于多线程的工具相关的开销,从而找出最佳方法。
-
@stark:如果要越过湖泊,就得坐船去。 如果要在道路上旅行,则需要开车。 因此,比较它们的速度是没有意义的。