OpenCL内核是否异步执行?

时间:2019-11-20 03:10:55

标签: c++ asynchronous opencl gpgpu

对于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);

命令入队后,kernel1kernel2是否会异步执行?(即,执行重叠)

更新
根据{{​​3}},在properties中将CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE设置为clCreateCommandQueue似乎可以满足我的需要。但是,out_of_order意味着异步吗?

2 个答案:

答案 0 :(得分:6)

  

out_of_order是否意味着异步

“乱序”队列表示内核 的执行顺序可能与排队的顺序不同(如果事件/数据相关性允许)。它们也可以同时执行,但不一定。

此外,异步执行意味着除执行重叠之外的其他东西(称为并行执行或并发)。异步执行意味着设备上的内核代码独立于主机代码执行-在OpenCL中始终如此。

获得并发(执行重叠)的简单方法是在同一设备上使用> 1个队列。即使在不具有乱序队列功能的实现上也可以使用。它不会保证执行重叠(因为与CUDA相比,OpenCL可以在更多设备上使用,并且在某些设备上您一次 不能一次执行> 1内核) ,但以我使用大多数GPU的经验来看,您应该至少有 some 个重叠部分。不过,您需要注意内核在单独队列中使用的缓冲区。

答案 1 :(得分:2)

在您当前的代码中:

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规范中的同步命令来确保数据的同步。