OpenCL 内核是异步执行的吗?
Are OpenCL kernels executed asynchronously?
对于 CUDA,我知道它们是在向默认流(空流)发出启动命令后异步执行的,那么在 OpenCL 中呢?示例代码如下:
cl_context context;
cl_device_id device_id;
cl_int err;
...
cl_kernel kernel1;
cl_kernel kernel2;
cl_command_queue Q = clCreateCommandQueue(context, device_id, 0, &err);
...
size_t global_w_offset[3] = {0,0,0};
size_t global_w_size[3] = {16,16,1};
size_t local_w_size[3] = {16,16,1};
err = clEnqueueNDRangeKernel(Q, kernel1, 3, global_w_offset, global_w_size,
local_w_size, 0, nullptr, nullptr);
err = clEnqueueNDRangeKernel(Q, kernel2, 3, global_w_offset, global_w_size,
local_w_size, 0, nullptr, nullptr);
clFinish(Q);
kernel1
和 kernel2
会在命令入队后异步执行吗?(即执行重叠)
更新
根据OpenCL Reference,看来clCreateCommandQueue
中设置properties
为CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
可以满足我的需要。但是,out_of_order是异步的意思吗?
在您当前的代码中:
err = clEnqueueNDRangeKernel(Q, kernel1, 3, global_w_offset, global_w_size,
local_w_size, 0, nullptr, nullptr);
err = clEnqueueNDRangeKernel(Q, kernel2, 3, global_w_offset, global_w_size,
local_w_size, 0, nullptr, nullptr);
kernel1
先完成然后kernel2
执行
正在使用
clCreateCommandQueue(context, device_id, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, &err);
虽然不保证可以同时执行多个不同的内核。
请注意,并非所有 OpenCL 实现都支持 CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
。这也意味着您无法保证 kernel1
会在 kernel2
之前完成执行。如果 kernel1
输出的任何对象需要作为 kernel2
中的输入,它可能会失败。
还可以创建多个命令队列并使用命令排队,它们存在的原因是因为您希望解决的问题可能涉及主机中的一些(如果不是全部的话)异构设备。它们可以表示不共享数据的独立计算流,也可以表示每个后续任务都依赖于前一个任务(通常是共享数据)的依赖计算流。但是,如果不共享数据,这些命令队列将在不同步的情况下在设备上执行。如果共享数据,则程序员需要使用 OpenCL 规范中的同步命令来确保数据同步。
Does out_of_order mean asynchronization
"Out of order" 队列意味着内核 可能 以不同于排队的顺序执行(如果它们的 event/data 依赖项允许)。它们还可以并发执行,但不一定。
另外,异步执行意味着不同于执行重叠的东西(这叫做并行执行或并发)。异步执行意味着设备上的内核代码独立于主机代码执行 - 这在 OpenCL 中始终如此。
获得并发(执行重叠)的简单方法是在同一设备上使用 >1 个队列。这甚至适用于没有乱序队列功能的实现。它不 保证 执行重叠(因为 OpenCL 可以在比 CUDA 更多的设备上使用,并且在某些设备上你根本 不能 执行 >一次 1 个内核),但根据我对大多数 GPU 的经验,你应该至少得到 一些 重叠。不过,您需要注意内核在单独队列中使用的缓冲区。
对于 CUDA,我知道它们是在向默认流(空流)发出启动命令后异步执行的,那么在 OpenCL 中呢?示例代码如下:
cl_context context;
cl_device_id device_id;
cl_int err;
...
cl_kernel kernel1;
cl_kernel kernel2;
cl_command_queue Q = clCreateCommandQueue(context, device_id, 0, &err);
...
size_t global_w_offset[3] = {0,0,0};
size_t global_w_size[3] = {16,16,1};
size_t local_w_size[3] = {16,16,1};
err = clEnqueueNDRangeKernel(Q, kernel1, 3, global_w_offset, global_w_size,
local_w_size, 0, nullptr, nullptr);
err = clEnqueueNDRangeKernel(Q, kernel2, 3, global_w_offset, global_w_size,
local_w_size, 0, nullptr, nullptr);
clFinish(Q);
kernel1
和 kernel2
会在命令入队后异步执行吗?(即执行重叠)
更新
根据OpenCL Reference,看来clCreateCommandQueue
中设置properties
为CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
可以满足我的需要。但是,out_of_order是异步的意思吗?
在您当前的代码中:
err = clEnqueueNDRangeKernel(Q, kernel1, 3, global_w_offset, global_w_size,
local_w_size, 0, nullptr, nullptr);
err = clEnqueueNDRangeKernel(Q, kernel2, 3, global_w_offset, global_w_size,
local_w_size, 0, nullptr, nullptr);
kernel1
先完成然后kernel2
执行
正在使用
clCreateCommandQueue(context, device_id, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, &err);
虽然不保证可以同时执行多个不同的内核。
请注意,并非所有 OpenCL 实现都支持 CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
。这也意味着您无法保证 kernel1
会在 kernel2
之前完成执行。如果 kernel1
输出的任何对象需要作为 kernel2
中的输入,它可能会失败。
还可以创建多个命令队列并使用命令排队,它们存在的原因是因为您希望解决的问题可能涉及主机中的一些(如果不是全部的话)异构设备。它们可以表示不共享数据的独立计算流,也可以表示每个后续任务都依赖于前一个任务(通常是共享数据)的依赖计算流。但是,如果不共享数据,这些命令队列将在不同步的情况下在设备上执行。如果共享数据,则程序员需要使用 OpenCL 规范中的同步命令来确保数据同步。
Does out_of_order mean asynchronization
"Out of order" 队列意味着内核 可能 以不同于排队的顺序执行(如果它们的 event/data 依赖项允许)。它们还可以并发执行,但不一定。
另外,异步执行意味着不同于执行重叠的东西(这叫做并行执行或并发)。异步执行意味着设备上的内核代码独立于主机代码执行 - 这在 OpenCL 中始终如此。
获得并发(执行重叠)的简单方法是在同一设备上使用 >1 个队列。这甚至适用于没有乱序队列功能的实现。它不 保证 执行重叠(因为 OpenCL 可以在比 CUDA 更多的设备上使用,并且在某些设备上你根本 不能 执行 >一次 1 个内核),但根据我对大多数 GPU 的经验,你应该至少得到 一些 重叠。不过,您需要注意内核在单独队列中使用的缓冲区。