依然是NVPROF的research。获取数据需要记录GPU运行的总时间。因为Cuda基于C/C++,毫无疑问使用C++的Timer是可行的。但是time.h中的clock函数精度受制于 时钟计时单元的长度,即通常精度也为1毫秒,故还是推荐使用Cuda事件来进行时间测量:
cudaError_t cudaEventCreate( cudaEvent_t* event )---创建事件对象;
cudaError_t cudaEventRecord( cudaEvent_t event,CUstream stream )--- 记录事件;
cudaError_t cudaEventElapsedTime( float* time_ms,cudaEvent_t start,cudaEvent_t end )---计算两次事件之间相差的时间;
cudaError_t cudaEventDestroy( cudaEvent_t event )---销毁事件对象
cudaEventElapsedTime函数计算两次事件之间相差的时间。如果尚未记录其中任何一个事件,此函数将返回cudaErrorInvalidValue。如果记录其中任何一个事件使用了非零流,则结果不确定。计算的结果存函数的第一个参数中,默认单位是毫秒(ms),但函数的精度为0.5微秒(us)。
一个完整的例子, 来自CUDA_C_Best_Practices_Guide :
cudaEvent_t start, stop;
float time;
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord( start, 0 );
kernel<<>> ( d_odata, d_idata, size_x, size_y, NUM_REPS);
cudaEventRecord( stop, 0 );
cudaEventSynchronize( stop );
cudaEventElapsedTime( &time, start, stop );
cudaEventDestroy( start );
cudaEventDestroy( stop );
需要注意的是函数cudaEventSynchronize() 不可或缺,缺少的话算出来的时间永远是0.000。而且这个函数必须放在两个EventRecord之后而不是之前!
因为CUDA的kernel函数是以异步方式执行的,调用后立刻返回,这会导致计时不准确。cudaEventSynchronize(stop)会使得直到GPU执行完cudaEventRecord(stop, 0)之前的所有语句时,事件stop才会被记录下来,即起到同步的作用。