【问题标题】:Why isn't atomic double fully implemented为什么原子双重没有完全实现
【发布时间】:2015-07-14 22:12:06
【问题描述】:

我的问题很简单。为什么不是std::atomic<double> implemented completely?我知道这与原子 RMW(读-修改-写)访问有关。但我真的不明白,为什么这在double 上是不可能的。

指定可以使用任何trivially copyable 类型。当然double 也在其中。因此,C++11 需要可用于任何类类型的基本操作(加载、存储、CAS、交换等)。

但是,对于整数,可以进行一组额外的操作(fetch_add、++、+= 等)。

double 与这些类型几乎没有区别。它是原生的、可轻松复制的等等。为什么标准没有将double 包含在这些类型中?


更新:C++20 确实将 std::atomic&lt;T&gt; 专门用于浮点类型,带有 fetch_add 和 sub。 C++20 std::atomic<float>- std::atomic<double>.specializations 但不是原子绝对值 (AND) 或否定 (XOR)。

编者注:如果没有 C++20,您可以将自己的代码从 CAS 中推出;有关可移植示例,请参见Atomic double floating point or SSE/AVX vector load/store on x86_64; atomic&lt;double&gt; 和 float 在大多数 C++ 实现中都是无锁的。

【问题讨论】:

  • 我猜原因是大多数 CPU 不支持原子 double 操作。那么你将如何实现呢?
  • @Damon:标准不关心寄存器。 “可简单复制”就是使用 memcpy(简单地说)从一个内存位置复制到另一个内存位置。如果不支持该架构,那它一定很奇怪。
  • 但无论如何,SSE2 是 64 位的基准,并且许多 32 位软件都是在启用 SSE2 的情况下构建的。在这种情况下,绝对没有什么奇怪的。无论哪种方式,std::atomic&lt;double&gt; 在 gcc/clang/msvc 上都是无锁的。 stackoverflow.com/questions/45055402/…
  • @curiousguy:“平凡可复制”,而不是“可复制”是正确的拼写。我只提到这一点,以防您要编辑其他任何内容以进行相同的更改。您编辑的其余部分看起来很合理。 “interlocked”是在询问是否可以使用 x86 Windows 术语实现底层实现,这还不错,但可以肯定的是,对原子 RMW 的硬件支持是一回事。
  • @curiousguy:见docs.microsoft.com/en-us/windows/win32/api/winnt/…和朋友,喜欢InterlockedXor64

标签: c++ floating-point atomic compare-and-swap stdatomic


【解决方案1】:

标准库要求std::atomic&lt;T&gt;,其中T 是任何TriviallyCopyable 类型。因为double 是TriviallyCopyable,所以std::atomic&lt;double&gt; 应该可以很好地编译和工作。

如果没有,说明你的库有问题。

编辑:因为评论澄清了问题:

c++ 标准为基本整数类型指定了特定的特化。 (即包含需要在语言中出现的整数的类型)。这些专业化对 atomic 的一般情况有进一步的要求,因为它们必须支持:

  • fetch_add
  • fetch_sub
  • fetch_and
  • fetch_or
  • fetch_xor
  • 运算符++
  • 操作员--
  • 比较和赋值运算符

OR、XOR、AND 当然与浮点类型无关,甚至比较也开始变得棘手(因为需要处理 epsilon)。因此,强制图书馆维护者在没有支持需求的情况下提供特定的专业化似乎是不合理的。

当然,没有什么可以阻止库维护者提供这种专业化,万一给定架构支持两个双精度的原子异或(它永远不会!)。

【讨论】:

  • 我应该更清楚。我会扩大我的问题。但是在我在问题中链接到的页面上。列出了许多类型以具有 std::atomic 的完整特化。 Double 不在其中。
  • 原子与与fabs() 相关(清除符号位)。 XOR/OR 也可以有效地混淆符号位。有趣的事实:C++ 标准提案 (open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0020r5.html) 计划将 fetch_add 添加到原子浮点类型,因为显然某些硬件有效地支持它。另请参阅Atomic double floating point or SSE/AVX vector load/store on x86_64 以了解 asm 的观点,以及一些低效的编译器输出:(
  • 有趣。谢谢@PeterCordes
  • 上面的链接已经失效了
  • @phuclv 是的,我明白了。我会删除它
【解决方案2】:

std::atomic&lt;double&gt; 是受支持的,因为您可以在程序中创建一个,它将在 C++11 的规则下工作。您可以使用它执行加载和存储,并进行比较交换等。

标准规定算术运算(+、*、+=、& 等)仅提供给“整数类型”的原子,因此std::atomic&lt;double&gt; 不会定义任何这些运算。

我的理解是,由于在当今使用的硬件中几乎不支持 fetch-add 或任何其他针对浮点类型的原子算术运算,因此 C++ 标准没有为它们提供运算符,因为它们必须是实施效率低下。

(编辑)。顺便说一句,VS2015RC 中的std::atomic&lt;double&gt; 是无锁的。

【讨论】:

  • 顺便说一句,看起来 std::atomic 现在 (C++20) 需要对 fetch_add/fetch_sub 提供一些支持。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-08
  • 2012-11-29
  • 2013-09-02
  • 2014-10-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多