测量OpenCL应用程序的经过时间

时间:2018-06-20 19:44:49

标签: c++ opencl timing

我知道这个问题已经被问过几次了,但是在我的应用程序中,把握时间是至关重要的,所以我可能想再试一次:

我用这样的内核方法计算时间,首先用clock_t计算CPU时钟时间;

clock_t start = clock(); // Or std::chrono::system_clock::now() for WALL CLOCK TIME
openCLFunction();
clock_t end = clock; // Or std::chrono::system_clock::now() for WALL CLOCK TIME
double time_elapsed = start-end;

还有我的openCLFunction():

{
//some OpenCLKernelfunction
clFlush(queue);
clFinish(queue);
}

两种方法的结果有很大的不同,老实说,我不知道哪种方法正确,因为它们以毫秒为单位。我可以相信CPU时钟时间吗?有没有一种确定的测量方法而无需考虑结果?(请注意,我调用了两个函数来完成我的内核函数。)

2 个答案:

答案 0 :(得分:2)

您可能应该使用内核配置文件。

cl_command_queue_properties properties[] {CL_QUEUE_PROPERTIES, CL_QUEUE_PROFILING_ENABLE, 0};
cl_command_queue queue = clCreateCommandQueueWithProperties(context, device, properties, &err);

/*Later...*/
cl_event event;
clEnqueueNDRangeKernel(queue, kernel, /*...*/, &event);
clWaitForEvents(1, &event);
cl_ulong start, end;
clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START, sizeof(cl_ulong), &start, nullptr);
clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END, sizeof(cl_ulong), &end, nullptr);

std::chrono::nanoseconds duration{end - start};

在该代码的末尾,duration包含在开始和结束之间传递的纳秒数(精确报告的设备能力;请注意,许多设备不具有亚微秒精度)执行内核。

答案 1 :(得分:2)

(至少)有3种时间来执行OpenCL / CUDA执行时间:

  1. 使用CPU计时器+队列刷新
  2. 使用OpenCL / CUDA事件
  3. 使用外部分析器工具(例如,AMD提供的任何产品或nVIDIA卡的nvprof)

您的第一个示例属于第一类,但是-您似乎似乎没有刷新OpenCL函数使用的队列(我假设这是一个使内核排队的函数)。因此-除非以某种方式强制执行同步,否则您要衡量的是排队内核并执行在此之前或之后执行的CPU端工作所需的时间。这可以解释clFlush / clFinish方法的差异。

造成差异的另一个原因可能是设置/拆卸工作(例如内存分配或运行时内部开销),而您的第二种方法却没有这种方法。

最后一点是,由于测量不准确或使用它们所需的开销不同,所有这三种方法都会产生略有不同的结果。但是,如果您的内核很小,这些差异可能不会那么小:根据我的经验,在CUDA中以及在nVIDIA的Maxwell和Pascal卡上,探查器提供的内核执行时间与事件测量时间的差异可能相差数十微秒。这个事实的教训是:1.尝试在相关且可能的情况下对更多数据进行度量,并根据数据量进行归一化。 2.在进行比较时如何衡量执行时间。