我注意到,使用重载std::complex
运算符而不是写出操作,乘以两个*
值会慢得多。我看到了50倍的差异。这完全是荒谬的。我知道运算符需要在输入中检查NaN,因为定义了无穷大的复杂程度。这真的能说明50倍的时差吗?
我使用带有标志-O3 -mavx -mavx2 -msse2 -mfma -mbmi
的GCC 5.4.0。
这是测试代码:
#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;
}
这是输出:
(-2.45689e+07,-134386) using manual *: 0.109344
(-2.45689e+07,-134386) using stdlib *: 5.4286
编辑:鉴于评论中人们的结果不同,我已经使用各种编译选项进行了更多测试。事实证明,-mfma
和-mavx
开关会导致&#34; stdlib&#34;版本太慢了。 -mfma
开关提供&#34;手册&#34;版本a~25%的性能提升,但减慢了&#34; stdlib&#34;版本大约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
我也尝试过clang-800(Mac OS),并没有看到这种极端减速。 Mac上的g ++ - 5与Linux上的g ++ - 5相同。也许我发现了编译器错误?
答案 0 :(得分:0)
我遇到了同样的问题,显然在Visual C ++中,复杂计算的性能降低了。以我为例,我是在Visual C ++的调试模式下进行时间测量的。切换到释放模式后,与双重计算相比,时间是合理的(考虑到复杂的操作包括多个双重计算)。