不使用 clWaitForEvents 的影响
Effect of not using clWaitForEvents
我是 OpenCL 编程的新手。在我的一个 OpenCL 应用程序中,我在启动每个内核后使用 clWaitForEvents。
案例一:
time_start();
cl_event event;
cl_int status = clEnqueueNDRangeKernel(queue, ..., &event);
clWaitForEvents(1, &event);
time_end();
耗时:250 毫秒(使用 clWaitForEvents)
如果我删除 clWaitForEvents(),我的内核在相同的输出下运行得更快。
案例二:
time_start();
cl_event event;
cl_int status = clEnqueueNDRangeKernel(queue, ..., &event);
time_end();
耗时:220 毫秒(没有 clWaitForEvents)
我必须依次启动 10 个不同的内核。每个内核都依赖于前一个内核的输出。在每个内核之后使用 clWaitForEvent 会使我的执行时间增加几百毫秒。
如果我不使用 clWaitForEvents,输出会出错吗?我想了解如果我不使用 clWaitForEvents 或 clFinish 可能会出现什么问题。
不胜感激。
In-order-queue
隐式等待每个命令按照它们入队的顺序完成,但仅在设备端。这意味着宿主无法知道发生了什么。
Out-of-order-queue
不保证在任何地方的任何命令顺序,并且可能会出现问题。
'Wait-for-event' 在主机端等待命令事件。
'Finish' 在主机端等待,直到所有命令完成。
'Non blocking buffer read/write' 不在主机端等待。
'Blocking buffer read/write' 在主机端等待,但不等待其他命令。
推荐的解决方案:
- 命令间同步(用于将命令的输出用作下一个命令的输入)
- 有序队列。
- 或将一个命令的事件传递给另一个(如果它是乱序队列)
- 队列间(或无序队列)同步(用于重叠缓冲区副本和内核执行)
- 将事件从命令传递到另一个命令
- 设备 - 主机同步(用于将最新数据获取到 RAM(或从 RAM 获取第一个数据)或暂停主机)
- 在缓冲区命令上启用阻止选项
- 或添加一个 clFinish
- 或使用 clWaitForEvent
- 命令完成时收到通知(出于基准测试等原因)
- 使用事件回调
- 或不断查询事件状态(CPU/pci-e 使用量增加)
在有序队列上排队 1 个非阻塞缓冲区写入 + 1000 x 内核 + 1 个阻塞缓冲区读取可以在初始数据上成功执行 1000 个内核链并在主机端获得最新结果。
希望答案稍微简单一点:
I've to launch 10 different kernels sequentially. Every kernel is dependent on the output of the previous kernel.
如果您没有在 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.
I would like to understand what might possibly go wrong if I do not use clWaitForEvents or clFinish.
如果您在单个有序队列上执行简单操作,则根本不需要 clWaitForEvents()。如果你想等待来自多个队列的多个事件,或者你正在使用无序队列,或者你想排队 20 个命令但等待第 4 个,或类似的东西,它最有用。
对于单个有序队列,在 clFinish() returns 之后,所有命令都将完成并且所有事件的状态都将更新为完成或失败。因此,在最简单的情况下,您根本不需要处理事件,只需将您需要的所有内容入队(尽管检查入队是否有错误)并调用 clFinish()。
请注意,如果您不使用任何形式的 wait/flush(WaitForEvents / Finish / 阻塞命令),实施可能需要尽可能多的时间才能将这些命令实际推送到设备。 IOW 您 必须 1) 使用 WaitForEvents 或 Finish,或 2) 将阻塞命令 (read/write/map/unmap) 作为 last 命令排队。
我是 OpenCL 编程的新手。在我的一个 OpenCL 应用程序中,我在启动每个内核后使用 clWaitForEvents。
案例一:
time_start();
cl_event event;
cl_int status = clEnqueueNDRangeKernel(queue, ..., &event);
clWaitForEvents(1, &event);
time_end();
耗时:250 毫秒(使用 clWaitForEvents)
如果我删除 clWaitForEvents(),我的内核在相同的输出下运行得更快。
案例二:
time_start();
cl_event event;
cl_int status = clEnqueueNDRangeKernel(queue, ..., &event);
time_end();
耗时:220 毫秒(没有 clWaitForEvents)
我必须依次启动 10 个不同的内核。每个内核都依赖于前一个内核的输出。在每个内核之后使用 clWaitForEvent 会使我的执行时间增加几百毫秒。
如果我不使用 clWaitForEvents,输出会出错吗?我想了解如果我不使用 clWaitForEvents 或 clFinish 可能会出现什么问题。
不胜感激。
In-order-queue
隐式等待每个命令按照它们入队的顺序完成,但仅在设备端。这意味着宿主无法知道发生了什么。
Out-of-order-queue
不保证在任何地方的任何命令顺序,并且可能会出现问题。
'Wait-for-event' 在主机端等待命令事件。
'Finish' 在主机端等待,直到所有命令完成。
'Non blocking buffer read/write' 不在主机端等待。
'Blocking buffer read/write' 在主机端等待,但不等待其他命令。
推荐的解决方案:
- 命令间同步(用于将命令的输出用作下一个命令的输入)
- 有序队列。
- 或将一个命令的事件传递给另一个(如果它是乱序队列)
- 队列间(或无序队列)同步(用于重叠缓冲区副本和内核执行)
- 将事件从命令传递到另一个命令
- 设备 - 主机同步(用于将最新数据获取到 RAM(或从 RAM 获取第一个数据)或暂停主机)
- 在缓冲区命令上启用阻止选项
- 或添加一个 clFinish
- 或使用 clWaitForEvent
- 命令完成时收到通知(出于基准测试等原因)
- 使用事件回调
- 或不断查询事件状态(CPU/pci-e 使用量增加)
在有序队列上排队 1 个非阻塞缓冲区写入 + 1000 x 内核 + 1 个阻塞缓冲区读取可以在初始数据上成功执行 1000 个内核链并在主机端获得最新结果。
希望答案稍微简单一点:
I've to launch 10 different kernels sequentially. Every kernel is dependent on the output of the previous kernel.
如果您没有在 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.
I would like to understand what might possibly go wrong if I do not use clWaitForEvents or clFinish.
如果您在单个有序队列上执行简单操作,则根本不需要 clWaitForEvents()。如果你想等待来自多个队列的多个事件,或者你正在使用无序队列,或者你想排队 20 个命令但等待第 4 个,或类似的东西,它最有用。
对于单个有序队列,在 clFinish() returns 之后,所有命令都将完成并且所有事件的状态都将更新为完成或失败。因此,在最简单的情况下,您根本不需要处理事件,只需将您需要的所有内容入队(尽管检查入队是否有错误)并调用 clFinish()。
请注意,如果您不使用任何形式的 wait/flush(WaitForEvents / Finish / 阻塞命令),实施可能需要尽可能多的时间才能将这些命令实际推送到设备。 IOW 您 必须 1) 使用 WaitForEvents 或 Finish,或 2) 将阻塞命令 (read/write/map/unmap) 作为 last 命令排队。