在GPU上运行FFTW与使用CUFFT

时间:2013-05-27 20:37:36

标签: cuda fftw cufft

我有一个基本的C ++ FFTW实现,如下所示:

for (int i = 0; i < N; i++){
     // declare pointers and plan
     fftw_complex *in, *out;
     fftw_plan p;

     // allocate 
     in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
     out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);

     // initialize "in"
     ...

     // create plan
     p = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);

     // execute plan
     fftw_execute(p);

     // clean up
     fftw_destroy_plan(p);
     fftw_free(in); fftw_free(out);
}

我在for循环中做N fft。我知道我可以使用FFTW一次执行许多计划,但在我的实现中 in out 在每个循环中都是不同的。重点是我正在整个FFTW管道INSIDE for for循环。

我想过渡到使用CUDA来加快速度。据我所知,CUDA有自己的FFT库CUFFT。语法非常相似:来自online documentation

#define NX 64
#define NY 64
#define NZ 128

cufftHandle plan;
cufftComplex *data1, *data2;
cudaMalloc((void**)&data1, sizeof(cufftComplex)*NX*NY*NZ);
cudaMalloc((void**)&data2, sizeof(cufftComplex)*NX*NY*NZ);
/* Create a 3D FFT plan. */
cufftPlan3d(&plan, NX, NY, NZ, CUFFT_C2C);

/* Transform the first signal in place. */
cufftExecC2C(plan, data1, data1, CUFFT_FORWARD);

/* Transform the second signal using the same plan. */
cufftExecC2C(plan, data2, data2, CUFFT_FORWARD);

/* Destroy the cuFFT plan. */
cufftDestroy(plan);
cudaFree(data1); cudaFree(data2);

然而,这些“内核”(如Nvida称之为)(cufftPlan3d,cufftExecC2C等)中的每一个都是来自GPU的调用。如果我正确理解了CUDA结构,那么每个方法调用都是单独的并行操作:

#define NX 64
#define NY 64
#define NZ 128

cufftHandle plan;
cufftComplex *data1, *data2;
cudaMalloc((void**)&data1, sizeof(cufftComplex)*NX*NY*NZ);
cudaMalloc((void**)&data2, sizeof(cufftComplex)*NX*NY*NZ);
/* Create a 3D FFT plan. */
cufftPlan3d(&plan, NX, NY, NZ, CUFFT_C2C); // DO THIS IN PARALLEL ON GPU, THEN COME BACK TO CPU

/* Transform the first signal in place. */
cufftExecC2C(plan, data1, data1, CUFFT_FORWARD); // DO THIS IN PARALLEL ON GPU, THEN COME BACK TO CPU

/* Transform the second signal using the same plan. */
cufftExecC2C(plan, data2, data2, CUFFT_FORWARD); // DO THIS IN PARALLEL ON GPU, THEN COME BACK TO CPU

/* Destroy the cuFFT plan. */
cufftDestroy(plan);
cudaFree(data1); cudaFree(data2);

我理解这可以通过在GPU上运行每个FFT步骤来加速我的代码。但是,如果我想并行化我的整个for循环怎么办?如果我希望每个原始N for循环在GPU上运行整个FFTW管道怎么办?我可以创建自定义“内核”并从设备(GPU)调用FFTW方法吗?

1 个答案:

答案 0 :(得分:3)

您无法从设备代码调用FFTW方法。 FFTW库是经过编译的x86代码,不能在GPU上运行。

如果代码中的“繁重提升”在FFT操作中,并且FFT操作的大小相当大,那么只需调用指示的cufft库例程就可以提供良好的加速并大致充分利用机器。一旦机器得到充分利用,尝试并行运行更多东西通常没有额外的好处。

cufft例程can be called by multiple host threads,因此可以对多个独立转换进行多次调用。如果单个变换足够大以利用机器,那么你不太可能从中看到太多的加速。

cufft还支持batched plans,这是另一种“同时”执行多个变换的方式。