Cuda 在GPU上运行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); }

Cuda 在GPU上运行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); },cuda,fftw,cufft,Cuda,Fftw,Cufft,然而,这些“内核”(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); cuda

然而,这些“内核”(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方法吗?

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

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

cufft例程,因此可以对cufft进行多个调用以进行多个独立的转换。如果单个变换足够大,可以使用机器,则不太可能从中看到太多的加速


cufft还支持“同时”执行多个转换的另一种方式。

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

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

cufft例程,因此可以对cufft进行多个调用以进行多个独立的转换。如果单个变换足够大,可以使用机器,则不太可能从中看到太多的加速


cufft还支持“同时”执行多个转换的另一种方式。

当您说“多个主机线程可以调用cufft例程,因此可以对cufft进行多个调用以进行多个独立的转换。”您的意思是我可以用另一种方式(比如openMP)并行化for循环吗?是的,我认为这应该是可能的。然而,我不确定它会提供多少,如果任何加速。如果您正在寻找加速,您可能需要考虑使用,这至少可以允许您将数据副本与Cufft处理重叠。当您说“Cufft例程可以由多个主机线程调用时,就可以对多个独立变换进行多个CUFFT调用。”你的意思是我可以用另一种方式(比如用openMP)并行我的for循环吗?是的,我相信这应该是可能的。然而,我不确定它会提供多少,如果任何加速。如果您正在寻找加速,您可能需要考虑使用,这至少可以让您将数据副本与Cufft处理重叠。除了GPU使用之外,我对基本FFTW使用有一点建议。只在循环内执行fftw_,并在for循环之前或之后移动任何其他fftw函数。立即执行内存分配,并在循环中使用相同的内存,以便在循环之前创建计划。同样,销毁计划并在for循环后释放分配的内存。请注意,创建计划可能会在循环中浪费大量时间。除了GPU的使用之外,我对fftw的基本用法有一些建议。只在循环内执行fftw_,并在for循环之前或之后移动任何其他fftw函数。立即执行内存分配,并在循环中使用相同的内存,以便在循环之前创建计划。同样,销毁计划并在for循环后释放分配的内存。请注意,创建计划可能会在循环中浪费大量时间。
#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);