最近在开发一个项目,用到大量线性变换(矩阵计算)和快速傅里叶变换(FFT)。
利用Eigen实现矩阵计算非常方便,在实现FFT时,借助了FFTW3库,但二者由于数据类型不同,需要转化,影响计算效率。
Eigen+FFTW3的计算需要1.7s,希望进一步提高算法的计算效率。
预算尝试Eigen库自带的FFT,相关资料如下:
EigenFFT
Eigen/FFT
可以看出,Eigen FFT并不成熟,借助了kissFFT实现的。
在stackoverflow网站上找到了参考代码,
eigen-fft-library
在本地计算机上试跑了代码
#define EIGEN_FFTW_DEFAULT
#include <iostream>
#include <unsupported/Eigen/FFT>
int main(int argc, char *argv[])
{
Eigen::MatrixXf A(3,3);
A << 2,1,2, 3,2,1, 1,2,3;
const int nRows = A.rows();
const int nCols = A.cols();
std::cout << A << "\n\n";
Eigen::MatrixXcf B(3,3);
Eigen::FFT< float > fft;
for (int k = 0; k < nRows; ++k) {
Eigen::VectorXcf tmpOut(nRows);
fft.fwd(tmpOut, A.row(k));
B.row(k) = tmpOut;
}
std::cout << B << "\n\n";
Eigen::FFT< float > fft2; // Workaround: Using the same FFT object for a real and a complex FFT seems not to work with FFTW
for (int k = 0; k < nCols; ++k) {
Eigen::VectorXcf tmpOut(nCols);
fft2.fwd(tmpOut, B.col(k));
B.col(k) = tmpOut;
}
std::cout << B << '\n';
}
输出结果如下:
当注释掉第一个for循环时,输出结果如下:
由此可以判断,两个for循环是相关的,一起实现了FFT。
可见,Eigen自带的FFT效率应该不高。
对了,在试跑上面的程序时,在fft.fwd语句处会报错,
error C4996: ‘std::copy::_Unchecked_iterators::_Deprecate’: Call to ‘std::copy’ with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ ‘Checked Iterators’
参考这个博客可解决:
Unchecked_iterators
打算继续用FFTW2,在与Eigen数据类型转化方面进行优化,并且采用FFTW3库自带的函数
fftwf_plan fftwf_plan_dft_r2c_2d(int n0, int n1,
float *in, fftwf_complex *out, unsigned flags);
进行FFT,避免输入数据额外补充虚部。