定时CUDA内核

时间:2012-06-17 09:33:16

标签: cuda

嗨,我现在正在为我的一些CUDA代码计时。我能够使用事件计时。我的内核运行了19毫秒。不知怎的,我发现这是值得怀疑的,因为当我运行这个顺序实现时,它大约是5000毫秒。我知道代码应该运行得更快,但它应该这么快吗?

我正在使用包装器函数在我的cpp程序中调用cuda内核。我应该在那里或.cu文件中调用它们吗?谢谢!

3 个答案:

答案 0 :(得分:1)

检查程序是否正常工作的明显方法是将输出与基于CPU的实现进行比较。如果你得到相同的输出,它按照定义工作,对吗? :)

如果你的程序是实验性的,它没有真正产生任何可验证的输出,那么编译器很可能已经优化了你的一些(或全部)代码。编译器将删除不对输出数据做出贡献的代码。例如,如果存储计算值的最终语句被注释掉,则可能导致内核的全部内容被删除。

关于你的加速。 5000ms / 19ms = 263x,即使对于完全映射到GPU架构的算法,也不太可能增加。

答案 1 :(得分:0)

好吧,如果你正确编写了你的​​CUDA代码,是的,它可能会快得多。想一想。您将代码从单个处理器上的顺序执行转移到数百个处理器上的并行执行,具体取决于您的GPU型号。我的179美元中档卡有480个核心。一些可用的现在有1500个核心。使用CUDA很可能获得100x perf跳转,特别是如果你的内核比内存绑定更加计算限制。

那就是说,确保你正在测量你认为你在测量的东西。如果在不使用任何显式流的情况下调用CUDA内核,则调用与主机线程同步,并且您的计时应该准确。如果使用流调用内核,则需要调用cudaDeviceSynchronise()或让主机代码等待内核发出的事件。在流上调用的内核调用以异步方式执行到主机线程,因此主机线程中的时间测量将无法正确反映内核时间,除非您使主机线程等待内核调用完成。您还可以使用CUDA事件来测量给定流中GPU上的已用时间。请参阅NVidia GPU计算SDK 4.2中的CUDA最佳实践指南的5.1.2节。

答案 2 :(得分:-3)

在我自己的代码中,我使用clock()函数来获得精确的时序。为方便起见,我有宏

enum {
    tid_this = 0,
    tid_that,
    tid_count
    };
__device__ float cuda_timers[ tid_count ];
#ifdef USETIMERS
 #define TIMER_TIC clock_t tic; if ( threadIdx.x == 0 ) tic = clock();
 #define TIMER_TOC(tid) clock_t toc = clock(); if ( threadIdx.x == 0 ) atomicAdd( &cuda_timers[tid] , ( toc > tic ) ? (toc - tic) : ( toc + (0xffffffff - tic) ) );
#else
 #define TIMER_TIC
 #define TIMER_TOC(tid)
#endif

然后可以使用这些来检测设备代码,如下所示:

__global__ mykernel ( ... ) {

    /* Start the timer. */
    TIMER_TIC

    /* Do stuff. */
    ...

    /* Stop the timer and store the results to the "timer_this" counter. */
    TIMER_TOC( tid_this );

    }

然后,您可以阅读主持人代码中的cuda_timers

一些注意事项:

  • 定时器以每个块为基础工作,即如果你有100个块执行相同的内核,则将存储所有时间的总和。
  • 计时器计算时钟滴答数。要获得毫秒数,请将其除以设备上的GHz数并乘以1000。
  • 计时器会让你的代码慢一点,这就是为什么我把它们包裹在#ifdef USETIMERS中,这样你就可以轻松地将它们关掉。
  • 虽然clock()返回类型为clock_t的整数值,但我将累积值存储为float,否则值将包含内核,这些内核需要的时间超过几秒(累积时间超过所有街区)。
  • 如果时钟计数器缠绕,则需要选择( toc > tic ) ? (toc - tic) : ( toc + (0xffffffff - tic) ) )