策略 - CUFFT在许多图像上计算2D FFT

时间:2016-04-06 01:38:29

标签: image matlab cuda cufft

我在128张图像上使用CUFFT进行2D FFT。每个图像的大小为128 x 128.在MATLAB上,进行一次2D FFT需要0.3 ms,而对所有128个图像进行FFT操作需要相当于该ms数量的128倍。使用CUFFT,执行以下代码计算一个图像的FFT

cudaMalloc( (void**)idata, sizeof(cufftDoubleReal) * 128 * 128 );
cudaMalloc( (void**)odata, sizeof(cufftDoubleComplex) * 128 * 128 );
cudaMemcpy( *idata, in_real, 128 * 128 * sizeof(cufftDoubleReal), 
                                  cudaMemcpyHostToDevice );
cudaMemcpy( *idata, in_complex, 128 * 128 * sizeof(cufftDoubleComples), 
                                  cudaMemcpyHostToDevice );

cufftExecD2Z( plan, idata, odata );
cudaMemcpy( out_complex, *odata, 128 * 128 * sizeof(cufftDoubleComplex), cudaMemcpyDeviceToHost );

我的机器需要大约0.4毫秒。

我尝试为多个图像执行相同的代码,执行时间基本上是0.4ms的多个图像的数量。我这样做的方式基本上是复制和粘贴上面的代码很多次,当然,变量对应的图像也是如此,这意味着

// For image1
cudaMalloc( (void**)idata, sizeof(cufftDoubleReal) * 128 * 128 );
cudaMalloc( (void**)odata, sizeof(cufftDoubleComplex) * 128 * 128 );
cudaMemcpy( *idata, in_real, 128 * 128 * sizeof(cufftDoubleReal), 
                                  cudaMemcpyHostToDevice );
cudaMemcpy( *idata, in_complex, 128 * 128 * sizeof(cufftDoubleComples), 
                                  cudaMemcpyHostToDevice );
cufftExecD2Z( plan, idata, odata );
cudaMemcpy( out_complex, *odata, 128 * 128 * sizeof(cufftDoubleComplex), cudaMemcpyDeviceToHost );

// For image 2
cudaMalloc( (void**)idata2, sizeof(cufftDoubleReal) * 128 * 128 );
cudaMalloc( (void**)odata2, sizeof(cufftDoubleComplex) * 128 * 128 );
cudaMemcpy( *idata2, in_real2, 128 * 128 * sizeof(cufftDoubleReal), 
                                  cudaMemcpyHostToDevice );
cudaMemcpy( *idata2, in_complex2, 128 * 128 * sizeof(cufftDoubleComples), 
                                  cudaMemcpyHostToDevice );
cufftExecD2Z( plan, idata2, odata2 );
cudaMemcpy( out_complex, *odata2, 128 * 128 * sizeof(cufftDoubleComplex), cudaMemcpyDeviceToHost );
...
// For image N
...

所以我可以期待如果我将2D FFT应用于所有128个图像,那么执行时间几乎与MATLAB的顺序相同。

所以我的问题是:我执行正确的执行方式是什么?我是否充分利用了GPU的并行计算能力?我是否应该修改执行代码的方式,例如,首先对所有128个图像执行cudaMemcpy并执行它们的时间,以便重叠一些CPU和GPU执行?

1 个答案:

答案 0 :(得分:4)

首先,我建议您分析您的代码。您不必分析所有100张图像,但可能需要2-5张图像。

根据配置文件数据,您应该比较传输数据所花费的时间与CUFFT操作所花费的时间。如果它们大致相等(或者如果您可以直观地看到重叠将是有益的),那么尝试重复和(CUFFT)计算的重叠,并且您将使用CUDA流来实现此目的。有很多关于CUDA流使用的教程以及关于CUDA标记(包括CUFFT标记)的示例问题,它们讨论了使用流和使用CUFFT的流。

另外,但与上述相关,我建议尝试使用CUFFT批处理参数将2-5个图像变换批处理,以查看是否会导致100个图像的整体处理时间净减少。

您实际上可以组合这两个想法,这意味着您可以批量执行转换,然后使用CUDA流使用复制/计算重叠来将与一批图像关联的复制操作与前一批的计算操作重叠。

除此之外,cudaMalloc操作费用昂贵。将它们放在性能(计算)循环中是最好的,这意味着,如果可能的话,在代码中预先运行它们一次。最好分配所需的所有空间(比如2-3批图像),然后重新使用空间,而不是为每个图像分配新的空间。