c++ - FFTW 高级布局——inembed=n 和 inembed=NULL 给出不同的结果?

标签 c++ c fft fftw

我正在使用 FFTW 高级数据布局 API 处理批量 2D FFT。

根据FFTW Advanced Complex DFT文档:

Passing NULL for an nembed parameter is equivalent to passing n.

但是,在使用 inembed = onembed = NULLinembed = 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]);
}

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*/);

我还使用 inembed = onembed = n = {nRows, nCols} 运行了这个版本。


结果

请注意,使用 NULLn 会得到相同的数值结果,但在内存中的顺序不同:

版本 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 

版本 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 

这是一个 working implementation of this experiment .

最佳答案

解决方案:
上例中 embed != NULL 的错位示例通过设置 inembed = {nRows, nCols}onembed = {nRows, (nCols/2 + 1)}


详细信息:

我在非常仔细阅读 FFTW 文档并从 Matteo Frigo 获得一些帮助后解决了这个问题.你可以在这里追溯我的步骤:

根据 4.4.2 Advanced Real-data DFTs在 FFTW 手册中:如果 nembed 参数为 NULL,则将其解释为基本界面中的内容。

假设我们输入的真实数据的维度是 nx * ny。 对于 FFTW 基本接口(interface),2.4 Multi-Dimensional DFTs of Real Data解释以下用于二维实数到复数 FFT 的 inembedonembed 约定:

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)]

所以,当我们使用简单的FFTWr2c接口(interface)或者使用带有embed=NULL的高级接口(interface)时,FFTW默认就是上面的embed参数。我们可以使用上述 embed 参数重现 embed=NULL 的数值结果。


原来语句Passing NULL for an nembed parameter is equivalent to passing n来自FFTW complex-to-complex手册页。但是,我们正在做 real-to-complex transforms在上面的例子中。对于 inembedonembed,实数到复数的转换与复数到复数的转换有不同的约定。

关于c++ - FFTW 高级布局——inembed=n 和 inembed=NULL 给出不同的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16905944/

相关文章:

c - 为什么 gcc 不为函数调用引用 PLT?

在没有实现的静态库中调用函数

android - 在android中每1/4秒获取音频文件的频率

c++ - 无法在 QWebEngineView 中登录 google : This app may not be secure

c++ - USB 到串行 UART 的位转换

c++ - 阻塞信号导致升压过程不起作用

c - C语言中如何用0替换数组中的重复项

python - NumPy 中 exp(-x^2) 的快速傅立叶变换

c - 不知道分配 float ,整数是否正确加倍

c++ - 运行时失败类包装 C 对象