为什么计算科学家需要实现自己的std :: complex版本?


14

许多计算科学较为著名的C ++库如Trilinosdeal.II使用标准的C ++模板库头对象std::complex<>,表示复杂的浮点数。

在Jack Poulson 回答有关默认构造函数的问题时,他指出,“出于多种原因” 他std::complexElemental中具有自己的实现。那是什么原因 这种方法的优点和缺点是什么?

Answers:


16

我相信这个讨论已经多次出现在PETSc清单上。我的主要原因是:

  1. C ++标准指出,std :: complex仅为float,double和long double数据类型定义。因此,它不能用于其他数据类型,例如四精度。

  2. 该标准不能保证复杂算法的稳定性。

  3. 该标准不保证std :: complex中的数据存储为实数部分,后跟虚数部分。这对于与外部库(例如BLAS和LAPACK)的接口至关重要。所有主要实现都是如此,但我希望能够确保实现。

  4. 我更喜欢能够直接操纵实部和虚部。std :: complex使此操作不必要地困难。

  5. 我希望最终有一个更通用的版本,该版本仅要求数据类型为环,而不要求字段。这将包括高斯整数。


6
第3点已在C ++ 11中解决。26.4.4指出,如果zcv 类型的左值表达式,std::complex<T>reinterpret_cast<cv T(&)[2]>(z)reinterpret_cast<cv T(&)[2]>(z)[0]将指定的实部z,并且reinterpret_cast<cv T(&)[2]>(z)[1]应指定的虚部z。还解决了复数数组。
James Custer 2012年

3
@JamesCuster:我全都愿意最终切换到C ++ 11,但是想要保留给半外来体系结构的科学代码可能需要至少等待两到三年才能这样做。同样,不幸的是,C ++ 11仅解决了部分问题。
Jack Poulson

我知道,我只是把它扔出去,以防将来有人看这个问题。
James Custer 2012年

2
好吧,我认为必须等到编译器支持C ++ 11才行。明确的要求已被纳入新标准,因为所有现有的实现都已支持该标准。我想不出在现有的编译器/库中已经假定这种特定布局是不安全的情况,因为以任何其他方式实现std :: complex根本没有任何意义。
Wolfgang Bangerth,2012年

1
@WolfgangBangerth:更多的是关于切换到C ++ 11的一般评论。无论哪种方式,C ++ 11都不能解决std :: complex的大多数问题。
Jack Poulson

7

std::complex<>在程序中使用,并且必须与编译器标志和每种新编译器或编译器升级的解决方法作斗争。我将尝试按时间顺序叙述这些斗争:

  1. std::norm|z|2|z|-ffast-math
  2. linux(或链接器)上的intel icc编译器std::arg在某些配置下(与特定gcc版本的链接兼容性)被编译为非opt。问题经常浮出水面,因此std::arg必须用代替atan2(imag(),real())。但是在编写新代码时忘记这一点太容易了。
  3. 该类型std::complex使用与内置C99复杂类型不同的调用约定(= ABI),并且对于较新的gcc版本使用内置的Fortran复杂类型。
  4. -ffast-math浮点异常以意想不到的方式的处理编译标志交互。发生的情况是编译器将除法从循环中拉出,从而division by zero在运行时导致异常。这些异常不会在循环内发生,因为相应的划分由于周围的逻辑而没有发生。那真的很糟糕,因为它是一个与使用浮点异常处理(使用不同的编译标志)的程序分开编译的库,并遇到了这些问题(相应的团队位于世界的相反部分,所以这个问题确实造成了严重的麻烦)。通过更仔细地手动进行编译器使用的优化来解决此问题。
  5. 该库已成为程序的一部分,并且不再使用-ffast-math编译标志。升级到较新的gcc版本后,性能下降了很多。我尚未对此问题进行详细调查,但我担心它与C99 Annex G有关。我必须承认,我对复数的乘积这个奇怪的定义完全感到困惑,甚至似乎存在这种说法的不同版本,并声称其他版本被误导了。我希望-fcx-limited-rangecompile标志可以解决该问题,因为-ffast-math对于此较新的gcc版本,似乎还存在另一个问题。
  6. 对于较新版本的gcc ,-ffast-math编译标志使行为NaN完全不可预测(甚至isnan会受影响)。唯一的解决方法似乎是避免NaN在程序中发生任何事件,这破坏了存在的目的NaN

现在您可能会问,std::complex出于这些原因,我是否打算放弃内置的复杂类型。只要我使用C ++,我就将使用内置类型。万一C ++应该变得完全无法用于科学计算,我宁愿考虑改用一种语言,该语言应更多地关注与科学计算有关的问题。


看起来我对C99附件G的担心已经实现,并且-fcx-limit-range现在是乘以复数时体面的计算速度所必需的。至少这是我从下面的近战的故事得到:medium.com/@smcallis_71148/...
托马斯Klimpel
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.