【发布时间】:2012-12-04 12:15:59
【问题描述】:
我正在开发一种算法,可以多次调用 FFT 函数。我有几个时间限制(需要实时),所以我需要尽量减少每次 FFT 调用所花费的时间。
我正在使用 OpenCV 库,并且已经使用两种不同的方法实现了我的代码:
- 使用 FFTW 库。数据/内存管理 + FFT(8ms) = 14ms(平均为 FFT_MEASURE 标志)。
- 使用 OpenCV fft 函数。数据/内存管理 + FFT (21ms) = 23ms(平均)。
由于我的输入数据始终固定为 512x512 像素的真实图像,您认为如果我自己实现基于 DFT 数学定义的 FFT 算法,存储正弦/余弦表可以实现更好的性能还是 FFTW库真的很优化吗?有更好的想法吗?
我们将不胜感激所有想法和建议。到目前为止,我不考虑并行化或 GPU 实现。
谢谢
更新:
系统:Windows 7 中的 Intel Xeon 5130 2.0GHz CPU、Visual Studio 10.0 和 FFTW 3.3.3(按照站点中的说明编译)、OpenCV 2.4.3。
使用 FFTW 进行 FFT 调用的代码示例(输入:OpenCV Mat CV_32F(1 通道,浮点型),输出 OpenCV Mat CV_32FC2(2 通道,浮点型):
float *im_data;
fftwf_complex *data_in;
fftwf_complex *fft;
fftwf_plan plan_f;
int i, j, k;
int height=I.rows;
int width=I.cols;
int N=height*width;
float* outdata = new float[2*N];
im_data = ( float* ) I.data;
data_in = ( fftwf_complex* )fftwf_malloc( sizeof( fftwf_complex ) * N );
fft = ( fftwf_complex* )fftwf_malloc( sizeof( fftwf_complex ) * N );
plan_f = fftwf_plan_dft_2d( height , width , data_in , fft , FFTW_FORWARD , FFTW_MEASURE );
for(int i = 0,k=0; i < height; ++i) {
float* row = I.ptr<float>(i);
for(int j = 0; j < width; j++) {
data_in[k][0]=(float)row[j];
data_in[k][1] =(float)0.0;
k++;
}
}
fftwf_execute( plan_f );
int width2=2*width;
// writing output matrix: RealFFT[0],ImaginaryFFT[0],RealFFT[1],ImaginaryFFT[1],...
for( i = 0, k = 0 ; i < height ; i++ ) {
for( j = 0 ; j < width2 ; j++ ) {
outdata[i * width2 + j] = ( float )fft[k][0];
outdata[i * width2 + j+1] = ( float )fft[k][1];
j++;
k++;
}
}
Mat fft_I(height,width,CV_32FC2,outdata);
fftwf_destroy_plan( plan_f );
fftwf_free( data_in );
fftwf_free( fft );
return fft_I;
【问题讨论】:
-
我尝试自己实现 fft,使用 sin\cos 表和其他优化。我真的认为自己提高fft速度并使其比fftw之类的库更快的唯一方法是在硬件中执行它。他们真的知道自己在做什么。
-
您可以进行内存管理,如果尺寸固定,您可以重复使用相同的内存块,而无需在每次迭代时执行分配(假设您不需要存储旧图像)跨度>
-
不要指望能够如此轻松地击败 FFTW。虽然这当然是可能的(我以前做过,因为这是我所做的),除非您对现代硬件有深入的了解以及高性能计算方面的经验,否则您不应该尝试。
-
数据/内存管理步骤中的其他 6 毫秒你在做什么?是否可以改进(更少的数据副本、矢量化操作等)?
-
我在数据/内存管理方面尽了最大的努力来优化这6ms,但我不是这方面的专家,所以肯定可以改进。我将在问题中放置我的代码示例。
标签: c++ optimization opencv fft fftw