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 库所独有的,用于实数到复数的变换以及复数到实数的逆变换。
我正在使用 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 库所独有的,用于实数到复数的变换以及复数到实数的逆变换。