Optimization CUDA内核中不同部分的计时

Optimization CUDA内核中不同部分的计时,optimization,cuda,benchmarking,Optimization,Cuda,Benchmarking,我有一个CUDA内核,可以调用一系列设备函数 获取每个设备功能的执行时间的最佳方法是什么 获取其中一个设备函数中一段代码的执行时间的最佳方法是什么?在我自己的代码中,我使用clock()函数获得精确的计时。为了方便起见,我有宏 enum { tid_this = 0, tid_that, tid_count }; __device__ float cuda_timers[ tid_count ]; #ifdef USETIMERS #define TIMER_T

我有一个CUDA内核,可以调用一系列设备函数

获取每个设备功能的执行时间的最佳方法是什么


获取其中一个设备函数中一段代码的执行时间的最佳方法是什么?

在我自己的代码中,我使用
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\u定时器

请注意:

  • 计时器以每个块为基础工作,即,如果有100个块执行同一内核,则将存储它们的所有时间之和
  • 话虽如此,计时器假定第0个线程处于活动状态,因此请确保不要在代码中可能存在分歧的部分调用这些宏
  • 计时器计算时钟滴答声的数量。要获得毫秒数,请将其除以设备上的GHz数,然后乘以1000
  • 计时器可以使代码慢一点,这就是为什么我将它们包装在
    #ifdef USETIMERS
    中,以便您可以轻松地关闭它们
  • 虽然
    clock()
    返回类型为
    clock\u t
    的整数值,但我将累积值存储为
    float
    ,否则,对于耗时数秒以上的内核(在所有块上累积),这些值将环绕
  • 选择<代码>(toc>tic)?(toc-tic):(toc+(0xffffffff-tic))
是时钟计数器环绕时所必需的
另外,这是我对的回复的副本,由于所需的时间是针对整个内核的,所以没有得到多少分数。

谢谢。非常有用。查找
clock()
,我发现还有一个
clock64()
,它可以消除溢出检查和浮点转换的需要。@RogerDahl:谢谢你指出这一点!它似乎是与CUDA 4.2一起添加的。费米添加了一个64位时钟结果。Clock64是在CUDA 4.2之前添加的。请注意,在执行这种类型的计时时,您必须小心发散——如果不同的扭曲在计时中采用不同的路径,则仅计时线程0将不准确。此外,还要确保反汇编编译器输出并确保没有发生重新排序。编译器和汇编器(至少是较旧的open64工具链)可以并且确实可以移动代码,这可能意味着时钟调用可以紧接着另一个,而不是括住您想要的代码。@harrism:我对此有点不精确。功能
clock64()
仅出现在CUDA编程指南(从版本4.2开始)中。关于你的第一点,我已相应地更新了我的答案。谢谢