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++ 的调试模式下进行了时间测量。切换到释放模式后,与双重计算相比,时间是合理的(考虑到复杂的操作包括多次双重计算)。