3

我有一个 opencl 内核批处理类,该类将 40 多个内核排入队列,并且每个内核执行之间都有一个 clFinish() 。

问题:当我注释掉 clFinish()s 然后程序运行速度提高 %100 时,这是否意味着当内核使用相同的缓冲区进行写入和读取时,内核之间存在未定义的行为?我怀疑性能提升来自更好地利用 gpu/占用资源。使用有序命令队列是否保证了两个内核之间的屏障,或者我需要它们之间的 clFinish() 吗?

它是一个简单的物理模型,两个版本之间没有可见的差异。

也许我只需要在最后使用 clFinish() ?

编辑:此命令队列未使用 CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE。

4

2 回答 2

7

如果所有内核调用都在同一个命令队列上执行并且这是一个有序队列,那么您不需要在内核调用之间使用clFinish,这正是您的场景,因此您不需要所有这些clFinish调用,只需保留最后一个。

性能差异来自以下因素的组合:

  • 每次clFinish调用都需要将所有排队的命令发送到设备并检查它们的执行状态。
  • 这些clFinish调用也会中断 GPU 正在完成的工作 - GPU 必须等待下一个内核入队并在之后发送到设备clFinish。省略调用clFinish意味着内核调用在之前的内核仍在执行时被发送到 GPU。
于 2013-08-27T21:36:06.043 回答
2

也许内核没有运行?将内核排队很便宜,并且不需要主机方面的任何努力。但是,调用 clEnqeueNDRangeKernel != 运行内核。

//Start host timer
clEnqueNDRangeKernel(...);
//Stop host timer - this doesn't actually time the kernel on the host

对比

//Start host timer
clEnqueueNDRangeKernel(...);
clFinish();
//Stop host timer - this does time the kernel on the host

或者,您可以使用内核分析和事件。

于 2013-08-28T01:36:51.013 回答