我正在使用 FFTW 高级数据布局 API 处理批量 2D FFT。
根据FFTW Advanced Complex DFT文档:
为 nembed 参数传递NULL相当于传递n。
inembed = onembed = NULL但是,在使用vs.时我得到了不同的结果inembed = onembed = n。什么可能导致结果不匹配?
让我们举个例子...
设置
int howMany = 2;
int nRows = 4;
int nCols = 4;
int n[2] = {nRows, nCols};
float* h_in = (float*)malloc(sizeof(float) * nRows*nCols*howMany);
for(int i=0; i<(nRows*nCols*howMany); i++){ //initialize h_in to [0 1 2 3 4 ...]
h_in[i] = (float)i;
printf("h_in[%d] = %f \n", i, h_in[i]);
}
Run Code Online (Sandbox Code Playgroud)
FFTW 计划使用inembed == onembed == NULL
fftwf_plan forwardPlan = fftwf_plan_many_dft_r2c(2, //rank
n, //dimensions = {nRows, nCols}
howMany, //howmany
h_in, //in
NULL, //inembed
howMany, //istride
1, //idist
h_freq, //out
NULL, //onembed
howMany, //ostride
1, //odist
FFTW_PATIENT /*flags*/);
Run Code Online (Sandbox Code Playgroud)
我还用 运行了一个版本inembed = onembed = n = {nRows, nCols}。
请注意,使用NULL或n给出相同的数值结果,但在内存中的顺序不同:
版本1:inembed == onembed == NULL
result[0][0,1] = 240, 0
result[1][0,1] = 256, 0
result[2][0,1] = -16, 16
result[3][0,1] = -16, 16
result[4][0,1] = -16, 0
result[5][0,1] = -16, 0 //this line and above match the other version
result[6][0,1] = -64, 64 //this line and below don't match (data is in a different order)
result[7][0,1] = -64, 64
result[8][0,1] = 0, 0
result[9][0,1] = 0, 0
result[10][0,1] = 0, 0
result[11][0,1] = 0, 0
result[12][0,1] = -64, 0
result[13][0,1] = -64, 0
result[14][0,1] = 0, 0
result[15][0,1] = 0, 0
result[16][0,1] = 0, 0
result[17][0,1] = 0, 0
result[18][0,1] = -64, -64
result[19][0,1] = -64, -64
result[20][0,1] = 0, 0
result[21][0,1] = 0, 0
result[22][0,1] = 0, 0
result[23][0,1] = 0, 0
result[24][0,1] = 0, 0
result[25][0,1] = 0, 0
result[26][0,1] = 0, 0
result[27][0,1] = 0, 0
result[28][0,1] = 0, 0
result[29][0,1] = 0, 0
result[30][0,1] = 0, 0
result[31][0,1] = 0, 0
Run Code Online (Sandbox Code Playgroud)
版本2:inembed = onembed = n = {nRows, nCols}
result[0][0,1] = 240, 0
result[1][0,1] = 256, 0
result[2][0,1] = -16, 16
result[3][0,1] = -16, 16
result[4][0,1] = -16, 0
result[5][0,1] = -16, 0
result[6][0,1] = 0, 0
result[7][0,1] = 0, 0
result[8][0,1] = -64, 64
result[9][0,1] = -64, 64
result[10][0,1] = 0, 0
result[11][0,1] = 0, 0
result[12][0,1] = 0, 0
result[13][0,1] = 0, 0
result[14][0,1] = 0, 0
result[15][0,1] = 0, 0
result[16][0,1] = -64, 0
result[17][0,1] = -64, 0
result[18][0,1] = 0, 0
result[19][0,1] = 0, 0
result[20][0,1] = 0, 0
result[21][0,1] = 0, 0
result[22][0,1] = 0, 0
result[23][0,1] = 0, 0
result[24][0,1] = -64, -64
result[25][0,1] = -64, -64
result[26][0,1] = 0, 0
result[27][0,1] = 0, 0
result[28][0,1] = 0, 0
result[29][0,1] = 0, 0
result[30][0,1] = 0, 0
result[31][0,1] = 0, 0
Run Code Online (Sandbox Code Playgroud)
这是该实验的有效实施。
解决办法:
上例中
的 和 不合适的情况可以通过设置和 来embed != NULL解决。
inembed = {nRows, nCols}onembed = {nRows, (nCols/2 + 1)}
细节:
在仔细阅读 FFTW 文档并从Matteo Frigo获得一些帮助后,我解决了这个问题。您可以在这里回顾我的步骤:
根据FFTW 手册中的4.4.2 Advanced Real-data DFT :If an nembed parameter is NULL, it is interpreted as what it would be in the basic interface.
假设我们输入的真实数据的维度为nx * ny。对于 FFTW 基本接口,2.4 实数据的多维 DFT解释了2D 实数到复数 FFT 的以下内容inembed和约定:onembed
if out-of-place:
inembed = [ny, nx]
onembed = [ny, (nx/2 + 1)]
if in-place:
inembed = [ny, 2(nx/2 + 1)]
onembed = [ny, (nx/2 + 1)]
Run Code Online (Sandbox Code Playgroud)
因此,当我们使用简单的 FFTWr2c接口或使用 的高级接口时embed=NULL,FFTW 默认为上述embed参数。embed=NULL我们可以使用上述参数重现数值结果embed。
事实证明,该语句Passing NULL for an nembed parameter is equivalent to passing n来自FFTW 复杂到复杂的手册页。但是,我们在上面的示例中进行实数到复数的转换。inembed对于和 ,实数到复数变换与复数到复数变换具有不同的约定onembed。