Opencl 不使用clWaitForEvents的影响

Opencl 不使用clWaitForEvents的影响,opencl,Opencl,我是OpenCL编程新手。在我的一个OpenCL应用程序中,我在启动每个内核后使用clWaitForEvents 案例1: time_start(); cl_event event; cl_int status = clEnqueueNDRangeKernel(queue, ..., &event); clWaitForEvents(1, &event); time_end(); 所用时间:250毫秒(带clWaitForEvents) 如果删除clWaitForEvents(

我是OpenCL编程新手。在我的一个OpenCL应用程序中,我在启动每个内核后使用clWaitForEvents

案例1:

time_start();
cl_event event;
cl_int status = clEnqueueNDRangeKernel(queue, ..., &event);
clWaitForEvents(1, &event);
time_end();
所用时间:250毫秒(带clWaitForEvents)

如果删除clWaitForEvents(),内核在相同的输出下运行得更快

案例2:

time_start();
cl_event event;
cl_int status = clEnqueueNDRangeKernel(queue, ..., &event);
time_end();
所用时间:220毫秒(无clWaitForEvents)

我必须按顺序推出10种不同的内核。每个内核都依赖于前一个内核的输出。在每个内核之后使用clWaitForEvent会将执行时间增加100毫秒

如果不使用clWaitForEvents,输出是否会出错?我想了解如果我不使用clWaitForEvents或clFinish,可能会出现什么问题


欢迎使用任何指针。

按顺序队列
隐式等待每个命令按其排队顺序完成,但仅在设备端。这意味着主持人不知道发生了什么

无序队列
不保证任何地方的任何命令顺序,可能会出现问题

“等待事件”在主机端等待命令的事件

“Finish”在主机端等待,直到所有命令完成

“非阻塞缓冲区读/写”不会在主机端等待

“阻止缓冲区读/写”在主机端等待,但不等待其他命令


建议的解决方案:

  • 命令间同步(用于将命令的输出用作下一个命令的输入)
    • 按顺序排队
    • 或将命令的事件传递给另一个(如果是无序队列)
  • 队列间(或无序队列)同步(用于重叠缓冲区拷贝和内核执行)
    • 将事件从命令传递到另一个命令
  • 设备-主机同步(用于向RAM获取最新数据(或从RAM获取第一个数据)或暂停主机)
    • 在缓冲区命令上启用阻塞选项
    • 或者添加一个clFinish
    • 或者使用clWaitForEvent
  • 命令完成时通知(出于基准测试等原因)
    • 使用事件回调
    • 或不断查询事件状态(CPU/pci-e使用量增加)


将1个非阻塞缓冲区写入+1000 x内核+1个阻塞缓冲区读取放入顺序队列,可以成功地在初始数据上执行1000个内核的链,并在主机端获得最新结果。

顺序队列
隐式地按照它们被放入队列的顺序等待每个命令完成,但仅在设备端。这意味着主持人不知道发生了什么

无序队列
不保证任何地方的任何命令顺序,可能会出现问题

“等待事件”在主机端等待命令的事件

“Finish”在主机端等待,直到所有命令完成

“非阻塞缓冲区读/写”不会在主机端等待

“阻止缓冲区读/写”在主机端等待,但不等待其他命令


建议的解决方案:

  • 命令间同步(用于将命令的输出用作下一个命令的输入)
    • 按顺序排队
    • 或将命令的事件传递给另一个(如果是无序队列)
  • 队列间(或无序队列)同步(用于重叠缓冲区拷贝和内核执行)
    • 将事件从命令传递到另一个命令
  • 设备-主机同步(用于向RAM获取最新数据(或从RAM获取第一个数据)或暂停主机)
    • 在缓冲区命令上启用阻塞选项
    • 或者添加一个clFinish
    • 或者使用clWaitForEvent
  • 命令完成时通知(出于基准测试等原因)
    • 使用事件回调
    • 或不断查询事件状态(CPU/pci-e使用量增加)


将1个非阻塞缓冲区写入+1000 x内核+1个阻塞缓冲区读取放入顺序队列,可以成功地在初始数据上执行1000个内核的链,并在主机端获得最新结果。

希望答案稍微简单一些:

我必须按顺序推出10种不同的内核。每个内核都依赖于前一个内核的输出

如果在clCreateCommandQueue()调用(=通常情况)中未显式设置CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE属性,则它将是一个按顺序队列。您不需要同步其中的命令(事实上,您不应该这样做,因为这样会大大降低执行速度)。见:


如果未设置命令队列的CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE属性,则排队到命令队列的命令将按顺序执行。例如,如果应用程序调用ClenqueEndRangeKernel来执行内核A,然后调用ClenqueEndRangeKernel来执行内核B,则应用程序可以假定内核A首先完成,然后执行内核B。如果内核A输出的内存对象是内核B的输入,那么内核B将看到内核A执行产生的内存对象中的正确数据。

我想了解如果我不使用clWaitForEvents或clFinish,可能会出现什么问题

如果您在单个顺序队列上执行简单的操作,则根本不需要clWaitForEvents()。如果您想等待来自多个队列的多个事件,或者您正在使用无序队列,或者您想将20个命令排入队列但等待第4个命令,或者类似的命令,那么它非常有用

对于单个顺序队列,在clFinish()返回后,所有命令都将完成,所有&all事件的状态都将更新为完成或失败。因此,在最简单的情况下,您根本不需要处理事件,只需将所有需要的内容排队(检查排队是否有错误)并调用clFinish()

请注意,如果您不使用任何形式的wait/flush(WaitForEvents/Finish/a blocking命令),那么实现可能需要与实际推送这些命令相同的时间