CUDA(CUFT)上的C2R FFT产生的结果与FFTW不同

CUDA(CUFT)上的C2R FFT产生的结果与FFTW不同,cuda,fft,fftw,fluid-dynamics,Cuda,Fft,Fftw,Fluid Dynamics,我正在研究将一些代码从使用FFTW库转换为CUFT(CPU计算到GPU计算)。我需要变换一个力矩阵,在上面做一些数学运算,然后再变换回来。FFTW中的操作如下所示: fftw_real u0[DIM * 2*(DIM/2+1)], v0[DIM * 2*(DIM/2+1)]; static rfftwnd_plan plan_rc, plan_cr; void init_FFT(int n) { plan_rc = rfftw2d_create_plan(n, n, FFTW_REAL_

我正在研究将一些代码从使用FFTW库转换为CUFT(CPU计算到GPU计算)。我需要变换一个力矩阵,在上面做一些数学运算,然后再变换回来。FFTW中的操作如下所示:

fftw_real u0[DIM * 2*(DIM/2+1)], v0[DIM * 2*(DIM/2+1)];

static rfftwnd_plan plan_rc, plan_cr;

void init_FFT(int n) {
  plan_rc = rfftw2d_create_plan(n, n, FFTW_REAL_TO_COMPLEX, FFTW_IN_PLACE);
  plan_cr = rfftw2d_create_plan(n, n, FFTW_COMPLEX_TO_REAL, FFTW_IN_PLACE);
}

#define FFT(s,u)\
  if(s==1) rfftwnd_one_real_to_complex(plan_rc,(fftw_real *)u,(fftw_complex*)u);\
  else rfftwnd_one_complex_to_real(plan_cr,(fftw_complex *)u,(fftw_real *)u)
最后:

FFT(1,u0);
FFT(1,v0);

//math
...

//and transforming back
FFT(-1,u0); 
FFT(-1,v0);
cufftExecR2C(planR2C, (cufftReal*) dev_forcesX, (cufftComplex*)dev_forcesX);
cufftExecR2C(planR2C, (cufftReal*) dev_forcesY, (cufftComplex*)dev_forcesY);


cudaMemcpy( forcesX, dev_forcesX, OURARRAYSIZE*sizeof(cufftReal), cudaMemcpyDeviceToHost );
cudaMemcpy( forcesY, dev_forcesY, OURARRAYSIZE*sizeof(cufftReal), cudaMemcpyDeviceToHost );

diffuseVelocity(velocitiesX, velocitiesY, forcesX, forcesY);//MATH PART

cudaMemcpy( dev_forcesX, forcesX, OURARRAYSIZE*sizeof(cufftReal), cudaMemcpyHostToDevice );
cudaMemcpy( dev_forcesY, forcesY, OURARRAYSIZE*sizeof(cufftReal), cudaMemcpyHostToDevice );

cufftExecC2R(planC2R, (cufftComplex*) dev_forcesX, (cufftReal*)dev_forcesX);
cufftExecC2R(planC2R, (cufftComplex*) dev_forcesY, (cufftReal*)dev_forcesY);

cudaMemcpy( forcesX, dev_forcesX, OURARRAYSIZE*sizeof(cufftReal), cudaMemcpyDeviceToHost );
cudaMemcpy( forcesY, dev_forcesY, OURARRAYSIZE*sizeof(cufftReal), cudaMemcpyDeviceToHost );
移动到CUFFT后:

#define OURARRAYSIZE (DIM * 2*(DIM/2+1))
#define DIM 16

cufftHandle planR2C;
cufftHandle planC2R;
cufftReal forcesX[OURARRAYSIZE];
cufftReal forcesY[OURARRAYSIZE];
cufftReal  *dev_forcesX;
cufftReal  *dev_forcesY;
初始化:

最后:

FFT(1,u0);
FFT(1,v0);

//math
...

//and transforming back
FFT(-1,u0); 
FFT(-1,v0);
cufftExecR2C(planR2C, (cufftReal*) dev_forcesX, (cufftComplex*)dev_forcesX);
cufftExecR2C(planR2C, (cufftReal*) dev_forcesY, (cufftComplex*)dev_forcesY);


cudaMemcpy( forcesX, dev_forcesX, OURARRAYSIZE*sizeof(cufftReal), cudaMemcpyDeviceToHost );
cudaMemcpy( forcesY, dev_forcesY, OURARRAYSIZE*sizeof(cufftReal), cudaMemcpyDeviceToHost );

diffuseVelocity(velocitiesX, velocitiesY, forcesX, forcesY);//MATH PART

cudaMemcpy( dev_forcesX, forcesX, OURARRAYSIZE*sizeof(cufftReal), cudaMemcpyHostToDevice );
cudaMemcpy( dev_forcesY, forcesY, OURARRAYSIZE*sizeof(cufftReal), cudaMemcpyHostToDevice );

cufftExecC2R(planC2R, (cufftComplex*) dev_forcesX, (cufftReal*)dev_forcesX);
cufftExecC2R(planC2R, (cufftComplex*) dev_forcesY, (cufftReal*)dev_forcesY);

cudaMemcpy( forcesX, dev_forcesX, OURARRAYSIZE*sizeof(cufftReal), cudaMemcpyDeviceToHost );
cudaMemcpy( forcesY, dev_forcesY, OURARRAYSIZE*sizeof(cufftReal), cudaMemcpyDeviceToHost );
在数学部分之后,两个程序持有完全相同的数据(矩阵)。不幸的是,经过反向傅里叶变换后,矩阵中的数据有所不同。我注意到损坏的数据是,它位于奖金列((DIM*2*(DIM/2+1)),这是就地转换所需要的


有人知道吗,为什么?关于CUFFT有什么我不知道的吗?

作为背景,您使用的是哪个CUDA版本,您使用的是什么GPU/OS平台?CUDA 4.2+Windows 7+NVidia GeForce 560这似乎是一个bug。你可以试试CUDA5.0RC,它可以向公众开放,但我建议你通过注册开发者网站提交一个bug。请附上您的复印件(尽可能简化会有帮助)。转到页面中间的文本“CUDA注册开发者程序的成员可以报告问题和文件错误|今天登录或加入”中的绿色链接,查找。与了解一点CUFFT的人交谈,他指出,如果行末尾有“填充”,则需要设置正确的间距(您的奖金栏将符合该描述)。应该有一种方法可以在CUFFT中处理此问题,但可能没有很好的文档记录,我不知道详细信息。也许了解CUFFT的人可以提供适用API的详细信息以及要传递的内容。结果证明根本没有错误。我在其他地方犯了错误。矩阵不同,因为它们可以。经过反向FFT填充后列包含一些随机值,这些值因库而异。无论如何,谢谢。您帮助我理解了填充并找到了我自己的错误。