测量OpenCL内核的执行时间

时间:2014-05-08 19:33:58

标签: profiling opencl

我有以下循环来衡量我的内核的时间:

double elapsed = 0;
cl_ulong time_start, time_end;
for (unsigned i = 0; i < NUMBER_OF_ITERATIONS; ++i)
{
    err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global, NULL, 0, NULL, &event); checkErr(err, "Kernel run");
    err = clWaitForEvents(1, &event); checkErr(err, "Kernel run wait fro event");
    err = clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START, sizeof(time_start), &time_start, NULL); checkErr(err, "Kernel run get time start");
    err = clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END, sizeof(time_end), &time_end, NULL); checkErr(err, "Kernel run get time end");
    elapsed += (time_end - time_start);
}

然后我将elapsed除以NUMBER_OF_ITERATIONS以获得最终估算值。但是,我担心单个内核的执行时间太小,因此会给我的测量带来不确定性。如何衡量所有NUMBER_OF_ITERATIONS内核组合所用的时间?

你能否建议一个分析工具,它可以帮助解决这个问题,因为我不需要以编程方式访问这些数据。我使用的是NVIDIA的OpenCL。

4 个答案:

答案 0 :(得分:10)

您需要按照以下步骤来衡量OpenCL内核执行时间的执行时间:

1.创建队列,在创建队列时启用分析:

cl_command_queue command_queue;
command_queue = clCreateCommandQueue(context, devices[deviceUsed], CL_QUEUE_PROFILING_ENABLE, &err);

2.启动内核时链接事件

cl_event event;
err=clEnqueueNDRangeKernel(queue, kernel, woridim, NULL, workgroupsize, NULL, 0, NULL, &event);

3.等待内核完成

clWaitForEvents(1, &event);

4.等待所有排队任务完成

clFinish(queue);

5.获取数据分析并计算内核执行时间(由OpenCL API返回,以纳秒为单位)

cl_ulong time_start;
cl_ulong time_end;

clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START, sizeof(time_start), &time_start, NULL);
clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END, sizeof(time_end), &time_end, NULL);

double nanoSeconds = time_end-time_start;
printf("OpenCl Execution time is: %0.3f milliseconds \n",nanoSeconds / 1000000.0);

答案 1 :(得分:3)

分析函数返回纳秒,并且非常准确(~50ns),但是,执行具有不同的执行时间,这取决于您无法控制的其他小问题。

这可以减少您想要衡量的问题:

  • 测量内核执行时间:您的方法是正确的,测量的平均执行时间的准确性将随着您增加N而增加。这仅考虑执行时间,不会产生任何开销考虑到了。

  • 测量内核执行时间+开销:您应该使用事件,但是从CL_PROFILING_COMMAND_SUBMIT开始测量,以解决额外的执行开销。

  • 衡量真正的主机端执行时间:您应该使用事件,但是从第一个事件开始到最后一个事件结束都要测量。使用CPU定时测量是另一种可能性。如果你想测量它,那么你应该从循环中删除waitforevents,以允许OpenCL系统的最大吞吐量(并且可以减少开销)。

回答工具问题,我建议使用nVIDIA visual profiler。 BUt以后不再适用于OpenCL,您应该使用Visual Studio Add on或nvprofiler的旧版本(CUDA 3.0)。

答案 2 :(得分:1)

测量的时间以纳秒为单位返回,但您是对的:计时器的分辨率较低。但是,我想知道当你说时间太短而无法准确测量时内核的实际执行时间(我的直觉是分辨率应该在微秒范围内)。

测量多次迭代总时间的最合适方法取决于&#34;倍数&#34;在这里意味着是NUMBER_OF_ITERATIONS=5还是NUMBER_OF_ITERATIONS=500000?如果迭代次数为&#34;大&#34;,您可能只使用系统时钟,可能使用Windows上的QueryPerformanceCounter等特定于操作系统的函数(例如,参见Is there a way to measure time up to micro seconds using C standard library?)但是,当然,系统时钟的精度可能低于OpenCL设备的精度,因此这是否有意义真正取决于迭代次数。

遗憾的是,NVIDIA从他们的Visual Profiler中删除了OpenCL支持,但是...

答案 3 :(得分:0)

在英特尔的OpenCL GPU实施方面,我已经成功完成了您的方法(每个内核的时间安排),并且更倾向于批量处理NDRanges流。

  • 另一种方法是运行N次,并使用标记事件测量时间,如this question中提出的方法(问题不是答案)。

  • 根据我的经验,短内核的时间通常至少在微秒范围内。

  • 您可以使用clGetDeviceInfo和CL_DEVICE_PROFILING_TIMER_RESOLUTION检查定时器分辨率(例如,我的设置为80 ns)。