测量CUDA内核时的时间有所不同

时间:2019-01-15 11:52:00

标签: c parallel-processing cuda gpu nvidia

我尝试测量CUDA内核函数花费的时间。我同时测量它的CPU和GPU时序。但是两者之间却有很大的不同。

当我使用NVIDIA分析器对其进行分析时,内核大约需要6毫秒,这正是我想要的。但是,当我在内核调用周围使用gettimeofday()来获取CPU计时时,该度量为15ms。我那里也没有任何memcpy电话。内核在单独的流中运行。并且类似的内核正在并发流中运行。

示例代码:

gettimeofday(start);
cudaEventRecord(startGPU);

Kernel <<<abc, xyz,stream>>>();
cudaDeviceSynchronize();

cudaEventRecord(stopGPU);
printf("Elapsed GPU time  = ");

gettimeofday(stop);
printf("Elapsed CPU time  = ");

我得到上面代码的结果:

经过的GPU时间= 6毫秒 经过的CPU时间= 15毫秒

这很奇怪,因为仅存在内核执行行。但是,内核参数是指针。记忆副本是否要占用额外的时间?但是我也没有在配置文件中的任何地方找到内存副本。任何线索将不胜感激。

2 个答案:

答案 0 :(得分:3)

基本上,您所测量的CPU时间就是它花费的时间

  1. 记录第一个事件
  2. 使用相应的参数设置内核启动,
  3. 将必要的命令发送到GPU,
  4. 在GPU上启动内核,
  5. 在GPU上执行内核,
  6. 等待GPU执行完成的通知返回到CPU,并且
  7. 记录第二个事件。

另外,请注意,您的CPU时间测量方法不仅会测量您的进程/线程所花费的处理时间,而且还会计算总的系统时间(这可能包括您在使用过程中其他进程/线程所花费的处理时间)。进程/线程甚至不一定在运行)。我必须承认,即使如此,您报告的CPU时间仍然比我通常期望的要大得多。但是我不确定上面是否确实有整个代码。实际上,考虑到printf()并没有真正打印出任何内容,我对此表示怀疑。因此,可能还有一些我们不知道的其他因素,您仍需要考虑这些因素以充分说明您的时间安排。

无论如何,很可能您进行的两次测量都没有实际测量您真正想要测量的东西。如果您对运行内核所需的时间感兴趣,请使用CUDA事件。但是,如果先同步然后才记录结束事件,则开始事件和结束事件之间的时间将是内核执行开始,等待内核执行完成的CPU之间的时间,以及之后可能花费的时间。记录下第二个事件,然后让那个事件进入GPU,这样您就可以在什么时候询问GPU。想一想标记之类的事件,这些事件标记了发送到GPU的命令流中的特定点。您最有可能实际上想写这个:

cudaEventRecord(startGPU, stream);       // mark start of kernel execution
Kernel<<<abc, xyz, stream>>>();
cudaEventRecord(stopGPU, stream);        // mark end of kernel execution
cudaEventSynchronize(stopGPU);   // wait for results to be available

,然后使用cudaEventElapsedTime()获取两个事件之间的时间。

还请注意,gettimeofday()not necessarily的一种获得高分辨率时序的可靠方法。在C ++中,您可以使用std::steady_clockstd::high_resolution_clock(仅在无法避免的情况下我才求助于后者,因为不能保证其稳定;请确保时钟稳定周期实际上足以满足您要测量的条件。

答案 1 :(得分:-1)

调试完相同的问题后,我发现cuda通常在第一次启动内核之前需要时间,如论坛中所述:https://devtalk.nvidia.com/default/topic/1042733/extremely-slow-cuda-api-calls-/?offset=3

内核之前的cuda运行时API具有6ms的cudaMalloc和14ms的cudaLaunch,这是造成额外延迟的原因。但是,随后的内核可以正常工作。 cudaLaunch耗时通常以毫秒为单位,因此,如果超出该时间,则肯定需要修复。

注意::如果您在while(1)循环(仅运行一次)中运行任何cuda内核,则必须在循环外进行分配。否则,您将最终像这样延迟。