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

时间:2012-09-28 19:14:48

标签: cuda fft fftw fluid-dynamics

我正在努力将一些代码从使用FFTW库转换为CUFFT(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);

搬到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;

初​​始化:

cufftPlan2d(&planR2C, DIM, DIM, CUFFT_R2C);
cufftPlan2d(&planC2R, DIM, DIM, CUFFT_C2R);
cufftSetCompatibilityMode(planR2C, CUFFT_COMPATIBILITY_FFTW_ALL);
cufftSetCompatibilityMode(planC2R, CUFFT_COMPATIBILITY_FFTW_ALL);
cudaMalloc( (void**)&dev_forcesX, OURARRAYSIZE*sizeof(cufftReal) );
cudaMalloc( (void**)&dev_forcesY, OURARRAYSIZE*sizeof(cufftReal) );

最后:

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的东西,我不知道吗?

1 个答案:

答案 0 :(得分:0)

我的代码中的小错误。解决。