我一直在我的一个项目中使用 2D FFT,并且无法使用两个不同的 FFT 库获得正确的结果。起初我以为我用错了,但在与 MATLAB 和 Linux GCC 参考实现进行比较后,现在我的编译器(MSVC 2013 express)似乎发生了一些险恶的事情。
我的测试用例如下:256x256 复杂到真正的 IFFT,单个 bin 为 255(X,Y 表示法为 0,255)设置为 10000。
使用 AMFFFT,我得到以下 2D 变换:
使用 FFTW,我得到以下 2D 变换:
如您所见,AMPFFT 版本有点“几乎”正确,但有一点很奇怪,每个样本都有条带,而 FFTW 版本到处都是,出去吃午饭了。
我获取了两个不同测试版本的输出并将它们与 MATLAB(技术上是 octave,它在引擎盖下使用 FFTW)进行了比较。我还在 Linux 下使用 GCC 为 FFTW 运行了相同的测试用例。这是第 127 行的一组测试中的一个片段(行号在技术上并不重要,因为我选择的 bin 所有行都应该是相同的):
在这个例子中,octave 和 Linux 实现代表正确的结果并遵循红线(octave 绘制为黑色,Linux 绘制为红色,它与 octave 完全一致)。MSVC 下的 FFTW 绘制为蓝色,AMP FFT 输出绘制为洋红色。正如你所看到的,AMPFFT 版本似乎几乎接近了,但其中有这种奇怪的高频纹波,而 MSVC 下的 FFTW 只是一团糟,有这种奇怪的“打包”外观。
在这个阶段,我只能将矛头指向 Visual Studio,但我不知道发生了什么或如何修复它。
这是我的两个测试程序:
FFTW 测试:
//fftwtest.cpp
//2 dimensional complex-to-real inverse FFT test.
//Produces a 256 x 256 real-valued matrix that is loadable by octave/MATLAB
#include <fstream>
#include <iostream>
#include <complex>
#include <fftw3.h>
int main(int argc, char** argv)
{
int FFTSIZE = 256;
std::complex<double>* cpxArray;
std::complex<double>* fftOut;
// cpxArray = new std::complex<double>[FFTSIZE * FFTSIZE];
//fftOut = new double[FFTSIZE * FFTSIZE];
fftOut = (std::complex<double>*)fftw_alloc_complex(FFTSIZE*FFTSIZE);
cpxArray = (std::complex<double>*)fftw_alloc_complex(FFTSIZE * FFTSIZE);
for(int i = 0; i < FFTSIZE * FFTSIZE; i++) cpxArray[i] = 0;
cpxArray[255] = std::complex<double>(10000, 0);
fftw_plan p = fftw_plan_dft_2d(FFTSIZE, FFTSIZE, (fftw_complex*)cpxArray, (fftw_complex*)fftOut, FFTW_BACKWARD, FFTW_DESTROY_INPUT | FFTW_ESTIMATE);
fftw_execute(p);
std::ofstream debugDump("debugdumpFFTW.txt");
for(int j = 0; j < FFTSIZE; j++)
{
for(int i = 0; i < FFTSIZE; i++)
{
debugDump << " " << fftOut[j * FFTSIZE + i].real();
}
debugDump << std::endl;
}
debugDump.close();
}
AMPFFT 测试:
//ampffttest.cpp
//2 dimensional complex-to-real inverse FFT test.
//Produces a 256 x 256 real-valued matrix that is loadable by octave/MATLAB
#include <amp_fft.h>
#include <fstream>
#include <iostream>
int main(int argc, char** argv)
{
int FFTSIZE = 256;
std::complex<float>* cpxArray;
float* fftOut;
cpxArray = new std::complex<float>[FFTSIZE * FFTSIZE];
fftOut = new float[FFTSIZE * FFTSIZE];
for(size_t i = 0; i < FFTSIZE * FFTSIZE; i++) cpxArray[i] = 0;
cpxArray[255] = std::complex<float>(10000, 0);
concurrency::extent<2> e(FFTSIZE, FFTSIZE);
std::cout << "E[0]: " << e[0] << " E[1]: " << e[1] << std::endl;
fft<float, 2> m_fft(e);
concurrency::array<float, 2> outpArray(concurrency::extent<2>(FFTSIZE, FFTSIZE));
concurrency::array<std::complex<float>, 2> inpArray(concurrency::extent<2>(FFTSIZE, FFTSIZE), cpxArray);
m_fft.inverse_transform(inpArray, outpArray);
std::vector<float> outVec = outpArray;
std::copy(outVec.begin(), outVec.end(), fftOut);
std::ofstream debugDump("debugdump.txt");
for(int j = 0; j < FFTSIZE; j++)
{
for(int i = 0; i < FFTSIZE; i++)
{
debugDump << " " << fftOut[j * FFTSIZE + i];
}
debugDump << std::endl;
}
}
这两个都是在 MSVC 2013 上为 win32 控制台应用程序使用股票设置编译的,FFTW 测试也在 Centos 6.4 和 GCC 4.4.7 下运行。两个 FFTW 测试都使用 FFTW 版本 3.3.4,并且同时测试了复杂到真实和复杂到复杂的计划(结果相同)。
有没有人对我可以尝试解决这个问题的 Visual Studio 编译器设置有丝毫线索?