【问题标题】:CUDA cufft library 2D FFT only the left half plane correctCUDA 袖口库 2D FFT 仅左半平面正确
【发布时间】:2016-04-11 01:46:16
【问题描述】:

我正在使用 CUFFT 库对 128 个尺寸为 128 x 128 的图像进行 2D 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 图像的大数组,它是一个双精度数组。我想从/到cufftDoubleReal和从/到cufftDoubleComplex的复数转换应该没有问题?我对计划的制定方式和参数有点怀疑,我试图在网上找到一些例子,但它们没有那么有用,也没有那么一致。然后我只是根据自己的理解通过programming guide设置参数。

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

【问题讨论】:

    标签: cuda fft cufft


    【解决方案1】:

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

    在许多实际应用中,输入向量是实值的。它可以 很容易证明,在这种情况下,输出满足 Hermitian 对称性 ( X k = X N - k * , 其中星号表示复数 共轭)。反之亦然:对于复厄米特输入 逆变换将是纯实值的。 cuFFT 需要 这种冗余的优势,只在上半年工作 厄米特向量

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

    【讨论】:

    • 谢谢@talonmies。我想那我有一个关于 CUDA 的问题。假设我变换了 im1 并得到了 im1_fft,并且我在傅里叶域中有另一个图像,不是对称的。然后我将这两个图像点积并得到一个产品图像,由于输入,其中一半为零。那么CUDA IFFT将如何保留已经归零的半平面像素信息(在这种情况下不是对称的)?或者,在这种情况下,我是否对 CUDA 中的两个图像都使用完整的 Z2Z 变换?这听起来像 CUDA Z2Z 和 D2Z 操作并不真正相互兼容?
    • 是的,如果您在频域中有任意数组,那么您应该使用 C2C(或 Z2Z 用于双精度)变换; C2R 和 R2C 变换在频域中假设 Hermitian 对称,因此如果您传入一个缺乏对称性的输入,那么您将得到错误的结果
    猜你喜欢
    • 2016-08-21
    • 2017-11-10
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 2019-04-24
    • 2018-08-26
    • 1970-01-01
    相关资源
    最近更新 更多