我有一个基本的 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 一次执行多个计划,但是在我的执行中,每个循环的进出都是不同的。关键是我正在 for 循环中执行整个 FFTW 管道。
我想过渡到使用 CUDA 来加快速度。我知道 CUDA 有自己的 FFT 库 CUFFT。语法非常相似:来自他们的在线文档:
#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 方法吗?