不使用clWaitForEvents的影响

问题描述 投票:0回答:2

我是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可能会出错。

任何指针都表示赞赏。

opencl
2个回答
2
投票

希望答案稍微复杂一点:

我要按顺序启动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)排队作为最后一个命令。


1
投票

In-order-queue隐式地按照它们排队的顺序等待每个命令完成,但仅在设备端。这意味着主人无法知道发生了什么。

Out-of-order-queue不保证任何地方的任何命令顺序,并可能有问题。

'等待事件'在主机端等待命令事件。

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

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

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


推荐解决方案

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

在有序队列中排队1个非阻塞缓冲区写入+ 1000个内核+ 1个阻塞缓冲区,可以在初始数据上成功执行1000个内核链,并在主机端获取最新结果。

© www.soinside.com 2019 - 2024. All rights reserved.