CUDA cufft 库 2D FFT 只有左半平面正确

CUDA cufft library 2D FFT only the left half plane correct

我正在使用 CUFFT 库对 128 张尺寸为 128 x 128 的图像进行二维 FFT。我使用图书馆的方式如下:

unsigned int nx = 128; unsigned int ny = 128; unsigned int nz = 128;
// Make 2D fft batch plan
int n[2] = {nx, ny};
int inembed[] = {nx, ny};
int onembed[] = {nx, ny};

cufftPlanMany(&plan,
            2, // rank
            n, // dimension
            inembed,
            1, // istride
            nx * ny, // idist
            onembed,
            1, //ostride
            nx * ny, // odist
            CUFFT_D2Z,
            nz);
cufftSetCompatibilityMode(plan,CUFFT_COMPATIBILITY_NATIVE)

// Create output array
complex<double>* out_complex = new complex<double>[nx * ny * nz];
// Initialize output array
for (unsigned int i = 0; i < nx * ny * nz; i++) {
   out_complex[i].real(0);
   out_complex[i].imag(0);
}
cudaMalloc( (void**)&idata, sizeof(cufftDoubleReal) * nx * ny * nz );
cudaMalloc( (void**)&odata, sizeof(cufftDoubleComplex) * nx * ny * nz );
cudaMemcpy( idata, in_real, nx * ny  * nz * sizeof(cufftDoubleReal), 
                                  cudaMemcpyHostToDevice )  );
cudaMemcpy( odata, out_complex, nx * ny * nz *  sizeof(cufftDoubleComplex), 
                                  cudaMemcpyHostToDevice )  );

cufftExecD2Z( plan, idata, odata );

cudaMemcpy( out_complex, odata, nx * ny * nz * sizeof(cufftDoubleComplex),
                                  cudaMemcpyDeviceToHost ) );

主机上的输入in_real是一个大数组,里面放着3D图片,是一个double数组。我想转换 to/from double from/to cufftDoubleReal 和 complex from/to cufftDoubleComplex 应该没有问题吧?我对计划的制定方式和参数有点怀疑,我试图在网上找到一些示例,但它们既没有帮助也不一致。然后我只是根据自己的理解通过 programming guide 设置参数。

如标题所示,输出部分正确(左半平面),右半平面为零,这让我很困惑。我尝试设置不同类型的兼容模式,但没有太大帮助。我要比较的版本是 MATLAB fft2()。

您需要(重新)阅读 documentation 以了解从实到复杂的转换。引用:

In many practical applications the input vector is real-valued. It can be easily shown that in this case the output satisfies Hermitian symmetry ( X k = X N − k ∗ , where the star denotes complex conjugation). The converse is also true: for complex-Hermitian input the inverse transform will be purely real-valued. cuFFT takes advantage of this redundancy and works only on the first half of the Hermitian vector

即实数到复数变换的输出是对称的,cuFFT 通过不计算冗余(对称)系数来利用这一点。因此,只得到"half" transform 的输出是正常的,因为其他"half" 是相同的。这不是 cuFFT、FFTW 和大多数其他高性能 FFT 库所独有的,用于实数到复数的变换以及复数到实数的逆变换。