使用循环来测量cuFFT的执行时间,时间与循环次数之间的关系不是线性的

时间:2014-01-14 23:30:49

标签: c++ c visual-studio-2012 cuda fft

基本上我想通过将cuFFT执行函数放在for循环中来测量cuFFT函数的时间成本,这是我第一次使用的代码(这是Nvidia网站中用于CUDA的简单示例):

顺便说一句,我的CPU是Intel I7-3630QM 2.40GHz,GPU是Nvidia NVS 5200M。我使用的平台是Visual Studio 2012和CUDA 5.5,操作系统是Windows 7,64位。

#include "cuda_runtime.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <cufft.h>
#include <cuda.h>
#include <cuda_runtime_api.h>

#define NX 1024
#define NY 1024

int main(int argc, char** argv) {

int i;
int Iter;
cufftHandle plan;//A data structure named plan containing all information needed for Fourier Transform.
cufftComplex *data1;//data structure to store the real value and complex value of the input and output of Fourier Transform.

cudaMalloc((void**)&data1, sizeof(cufftComplex)*NX*NY);//Prepare the NX*NY 2D Fourier Transform by alloc input values on GPU Memory

cufftPlan2d(&plan, NX, NY, CUFFT_C2C);//Prepare 2D Fourier Transform (NX*NY), type is C2C that is complex to complex.

Iter = 1000;

clock_t begin, end;
double cost;
begin = clock();

for (i = 0;i <Iter;i++){

    cufftExecC2C(plan, data1, data1, CUFFT_FORWARD);//Execute the Fourier Transform with input data in data1 and output result to data1, CUFFT_FORWARD means it is FFT not iFFT.
}
end = clock();
cost = (double)(end - begin) / CLOCKS_PER_SEC;
printf("%lf seconds\n", cost);

cufftDestroy(plan);
cudaFree(data1);

return 0;
}

该程序通常返回0.030s的时间,如果我将Iter的值(多少个循环)更改为1100,结果变为0.033s,如果Iter = 1200,结果为0.036s,这似乎是线性的

这一直保持正确,直到Iter = 1500,Iter = 1500的时间为0.195s,当Iter = 1600,时间= 0.431s时。

我不明白为什么时间成本是这样的,任何人都可以帮助我?

提前谢谢。

1 个答案:

答案 0 :(得分:4)

修改您的代码,如下所示:

cudaDeviceSynchronize();  // add this line
end = clock();

我相信你会得到理智的结果。

CUFFT函数是异步的,因此它们可以支持复制和计算的流重叠。这意味着它们在底层GPU操作完成之前返回。所以你的for循环实际上排队了大量的变换,一个接一个地执行。但是,当你完成你的计时时,它们不一定完成。我相信您正在观察的复杂行为与超出内核队列启动次数的内部队列深度有关,在其他请求必须等待队列插槽打开之前。但这不是核心问题。

核心问题是你的计时方法存在缺陷。这只是使用基于主机的计时方法来计算异步GPU活动时间所固有的危险的另一个例子。