std :: complex乘法非常慢

Cri*_*ngo 9 gcc c++-standard-library

我注意到std::complex使用重载*运算符比使用写出操作要多得多两倍.我看到了50倍的差异.这完全是荒谬的.我知道运算符需要在输入中检查NaN,因为定义了无穷大的复杂程度.这真的能说明50倍的时差吗?

我正在使用带有标志的GCC 5.4.0 -O3 -mavx -mavx2 -msse2 -mfma -mbmi.

这是测试代码:

#include <iostream>
#include <complex>
#include <chrono>
#include <vector>

int main( void ) {
  size_t N = 10000;
  std::vector< std::complex< double >> inbuf( N );
  for( size_t k = 0; k < N; ++k ) {
     inbuf[ k ] = std::complex< double >( std::rand(), std::rand() ) / ( double )RAND_MAX - 0.5;
  }

  std::complex< double > c2 = { 0, 0 };
  auto t0 = std::chrono::steady_clock::now();
  for( size_t i = 0; i < 10000; ++i ) {
     for( size_t j = 0; j < N - 1; ++j ) {
        double re = inbuf[ j ].real() * inbuf[ j + 1 ].real() - inbuf[ j ].imag() * inbuf[ j + 1 ].imag();
        double im = inbuf[ j ].real() * inbuf[ j + 1 ].imag() + inbuf[ j ].imag() * inbuf[ j + 1 ].real();
        c2.real( c2.real() + re );
        c2.imag( c2.imag() + im );
     }
  }
  auto t1 = std::chrono::steady_clock::now();
  double time = ( std::chrono::duration< float >( t1 - t0 ) ).count();
  std::cout << c2 << " using manual *: " << time << std::endl;

  c2 = { 0, 0 };
  t0 = std::chrono::steady_clock::now();
  for( size_t i = 0; i < 10000; ++i ) {
     for( size_t j = 0; j < N - 1; ++j ) {
        c2 += inbuf[ j ] * inbuf[ j + 1 ];
     }
  }
  t1 = std::chrono::steady_clock::now();
  time = ( std::chrono::duration< float >( t1 - t0 ) ).count();
  std::cout << c2 << " using stdlib *: " << time << std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

(-2.45689e+07,-134386) using manual *: 0.109344
(-2.45689e+07,-134386) using stdlib *: 5.4286
Run Code Online (Sandbox Code Playgroud)

编辑:鉴于评论中的人们给出了不同的结果,我已经使用各种编译选项进行了更多测试.事实证明,-mfma-mavx开关导致"stdlib"版本如此之慢.该-mfma开关为"手动"版本提供了约25%的性能提升,但减慢了"stdlib"版本约13x的速度:

cris@carrier:~/tmp/tests> g++ complex_test.cpp -o complex_test -O3 -std=c++11
cris@carrier:~/tmp/tests> ./complex_test                                     
(-2.45689e+07,-134386) using manual *:0.138276
(-2.45689e+07,-134386) using stdlib *:0.412056
cris@carrier:~/tmp/tests> g++ complex_test.cpp -o complex_test -O3 -mfma -std=c++11 
cris@carrier:~/tmp/tests> ./complex_test                                                  
(-2.45689e+07,-134386) using manual *:0.106551
(-2.45689e+07,-134386) using stdlib *:5.37662
Run Code Online (Sandbox Code Playgroud)

我也尝试过clang-800(Mac OS)并没有看到这种极端减速.Mac上的g ++ - 5与Linux上的g ++ - 5相同.也许我发现了编译器错误?

小智 0

我遇到了同样的问题,显然 Visual C++ 中复杂计算的性能很慢。就我而言,结果是我在 Visual C++ 的调试模式下进行了时间测量。切换到释放模式后,与双重计算相比,时间是合理的(考虑到复杂的操作包括多次双重计算)。