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について何かありますか?