同一个CUDA内核执行时间之间的巨大差异

时间:2012-11-16 07:06:19

标签: time cuda

我正在多次(30)次启动一组内核。  这些30的每个测试(它们都是确定性的,在每次测试时都会调用一组内核10次并且这个数字是固定的),在开始时,我做cudaSetDevice(0)并且一切都得到malloc'd和memcpy'd。  测试完成并执行时间后,所有内容都是cudaFree'd。

以下是我的程序的示例输出:

avg:  81.7189
times:
213.0105 202.8020 196.8834 202.4001 197.7123 215.4658 199.5302 198.6519 200.8467
203.7865 20.2014 20.1881 21.0537 20.8805 20.1986 20.6036 20.9458 20.9473 20.292
9 20.9167 21.0686 20.4563 24.5359 21.1530 21.7075 23.3320 20.5921 20.6506 19.933
1 20.8211

前10个内核大约需要200毫秒,而其他内核需要大约20毫秒。

显然每个内核都计算相同的值,它们都打印出正确的值。但是由于我以相同的顺序对每个测试进行malloc,所以GPU内存是否仍然具有与之前执行相同的值?

此外,内核不会返回错误,因为我正在检查它们。每个内核启动都有cudaThreadSynchronize()用于调试目的,并在它之后使用此宏进行错误检查:

#define CUDA_ERROR_CHECK  if( (error = cudaGetLastError()) != cudaSuccess) printf("CUDA error: %s\n", cudaGetErrorString(error));

为什么会这样?

我从Windows函数获取执行时间:

void StartCounter()
{
    LARGE_INTEGER li;
    if(!QueryPerformanceFrequency(&li))
        cout << "QueryPerformanceFrequency failed!\n";

    PCFreq = double(li.QuadPart)/1000.0;

    QueryPerformanceCounter(&li);
    CounterStart = li.QuadPart;
}

void StopCounter()
{
    LARGE_INTEGER li;
    QueryPerformanceCounter(&li);
    double time = double(li.QuadPart-CounterStart)/PCFreq;
    v.push_back(time);
}

修改

mallocs,copys和其他东西没有定时。我只计算执行时间(内核启动和同步)。

启用Visual Studio 2010的优化功能。一切都设定为最大化速度。 CUDA的优化也在进行中。

1 个答案:

答案 0 :(得分:1)

使用QueryPerformanceTime测量内核执行时间是错误的,因为主机呼叫设备和它们并行工作。你可以只测量通话时间。

要检查内核执行时间,请使用ahmad提到的cudaEvents

cudaEvent_t start, stop;
float time;
cudaEventCreate(&start);
cudaEventCreate(&stop);
...
cudaEventRecord(start, 0);
yourkernel <<< n_blocks, block_size >>> (a_d, N);
cudaEventRecord(stop, 0);
cudaEventSynchronize(stop);
... 
cudaEventElapsedTime(&time, start, stop);
printf ("Time for the kernel: %f ms\n", time);

如果您想使用QueryPerformanceTime,则必须致电

cudaDeviceSynchronize();
内核调用后

。它会等到内核停止。