我是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会使我的执行时间增加几百毫秒。
如果我不使用clWaitForEvents,输出会出错吗?我想了解如果我不使用clWaitForEvents或clFinish可能会出错。
任何指针都表示赞赏。
希望答案稍微复杂一点:
我要按顺序启动10个不同的内核。每个内核都依赖于以前内核的输出。
如果未在clCreateCommandQueue()调用(=通常情况)中显式设置CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE属性,则它将是有序队列。您不需要在其中同步命令(实际上您不应该,因为您看到它可能会大大减慢执行速度)。见docs:
If the CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE property of a command-queue is not set, the commands enqueued to a command-queue execute in order. For example, if an application calls clEnqueueNDRangeKernel to execute kernel A followed by a clEnqueueNDRangeKernel to execute kernel B, the application can assume that kernel A finishes first and then kernel B is executed. If the memory objects output by kernel A are inputs to kernel B then kernel B will see the correct data in memory objects produced by execution of kernel A.
我想了解如果我不使用clWaitForEvents或clFinish可能会出错。
如果您在单个有序队列中执行简单操作,则根本不需要clWaitForEvents()。如果您想要等待来自多个队列的多个事件,或者您正在使用无序队列,或者您想要排队20个命令但是等待第4个或类似的东西,那么它最有用。
对于单个有序队列,在clFinish()返回后,将完成所有命令,并且所有事件的状态都将更新为完成或失败。因此,在最简单的情况下,您根本不需要处理事件,只需将您需要的所有内容排入队列(尽管检查队列中的错误)并调用clFinish()。
请注意,如果您不使用任何形式的等待/刷新(WaitForEvents / Finish / a blocking命令),则实现可能需要花费尽可能多的时间来实际将这些命令推送到设备。 IOW你必须1)使用WaitForEvents或Finish,或2)将阻塞命令(read / write / map / unmap)排队作为最后一个命令。
In-order-queue
隐式地按照它们排队的顺序等待每个命令完成,但仅在设备端。这意味着主人无法知道发生了什么。
Out-of-order-queue
不保证任何地方的任何命令顺序,并可能有问题。
'等待事件'在主机端等待命令事件。
'Finish'在主机端等待,直到所有命令完成。
'非阻塞缓冲区读/写'不会在主机端等待。
“阻塞缓冲区读/写”在主机端等待,但不等待其他命令。
推荐解决方案
在有序队列中排队1个非阻塞缓冲区写入+ 1000个内核+ 1个阻塞缓冲区,可以在初始数据上成功执行1000个内核链,并在主机端获取最新结果。