【问题标题】:Measuring Elapsed Time for an OpenCL Application测量 OpenCL 应用程序的运行时间
【发布时间】:2018-06-20 19:44:48
【问题描述】:

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

我为这样的内核方法计算时间,首先用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 时钟时间吗?有没有一种确定的方法来测量而不关心结果?(请注意,我调用了两个函数来完成我的内核函数。)

【问题讨论】:

  • std::chrono::system_clock 为您提供经过的时间。 clock 为您提供 CPU 时间。它们是两种完全不同的东西。你想要哪一个取决于你的目标。

标签: c++ opencl timing


【解决方案1】:

(至少)有 3 种方式来计时 OpenCL/CUDA 执行:

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

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

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

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

【讨论】:

  • 嗨,感谢您的回答,我之所以使用 clFinish() 和 clFlush(),是因为我希望读者知道在该方法中,我等待内核完全执行并移动on,不仅仅是将内核添加到队列中。最初的问题是,通过刷新和完成队列,我能得到 CPU 时钟时间的正确答案吗?在我的情况下,这两种方法之间的差异非常显着,但我无法通过感知时间来判断哪种方法是正确的,例如 20 毫秒和 100 毫秒。
【解决方案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 包含在执行开始和结束之间经过的纳秒量(根据设备的能力精确报告;请注意,许多设备没有亚微秒精度)内核。

【讨论】:

  • 感谢您的回答,您能否进一步解释一下为什么我应该使用内核分析,而不是做我所做的事情?在方法中有 3 个不同的内核,我真的很想测量它们的总持续时间。
  • @TuấnPhạm 主机分析本身并不是很糟糕,但是如果您想精确计算完成任务所需的时间,您应该更喜欢在设备级别进行测量,而不是在主机级别。如果您确实需要在主机级别进行分析,请使用您已经在使用的相同代码,但将您的 clock_t 别名更改为 std::chrono::steady_clockstd::chrono::high_resolution_clock 而不是(您似乎已经在使用的)@987654326 @.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多