用于并发NDKernal启动的OpenCL多命令队列

时间:2014-10-09 21:01:52

标签: concurrency opencl gpu gpgpu multi-gpu

我试图运行vector vector的应用程序,我需要同时启动多个内核, 所以对于并发内核启动,在我的上一个问题中有人建议我使用多个命令队列。 我用数组定义

context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &err);
    for(i=0;i<num_ker;++i)
    {
queue[i] = clCreateCommandQueue(context, device_id, 0, &err);
    }

我得到一个错误“命令终止于信号11”,其中包括上述代码。

我使用for循环来启动内核和En-queue数据

 for(i=0;i<num_ker;++i)
 {
 err = clEnqueueNDRangeKernel(queue[i], kernel, 1, NULL, &globalSize, &localSize,
                                                          0, NULL, NULL);
 }

问题是我不确定我哪里出错了,我看到某个地方我们可以创建一系列命令队列,所以这就是我使用数组的原因。 另一个信息,当我不使用A for循环时,只需手动定义多个命令队列,它就可以正常工作。

1 个答案:

答案 0 :(得分:3)

我也读到了你的上一个问题,我认为你应该首先重新思考你真正想做的事情,以及OpenCL是否真的是这样做的。

  

OpenCL是用于主动并行处理和数据处理的API。   每个内核(或排队任务)在许多数据上并行运行的地方   这些值同时优于任何串行CPU处理多个数量级。

OpenCL的典型用例是运行数百万个工作项的1个内核。 如果更高级的应用程序可能需要多个不同内核的序列,以及CPU和GPU之间的特殊同步。

但并发性从来都不是必需的。(否则,单个核心CPU将无法执行任务,情况永远不会如此。它会更慢,没问题,但它仍然会可以运行它)

即使两个任务需要同时运行。所花费的时间将同时或不同:

不兼并案例:

Kernel 1: *
Kernel 2: -
GPU Core 1: *****-----
GPU Core 2: *****-----
GPU Core 3: *****-----
GPU Core 4: *****-----

并发案例:

Kernel 1: *
Kernel 2: -
GPU Core 1: **********
GPU Core 2: **********
GPU Core 3: ----------
GPU Core 4: ----------

事实上,非并发案例是首选,因为至少第一项任务已经完成,可以继续进一步处理。


据我所知,您想要做的是同时运行多个内核。这样内核就可以完全并发运行。例如,运行100个内核(相同内核或不同内核)并同时运行它们。

根本不适合OpenCL模型。事实上,它可能比CPU单线程慢。

如果每个内核独立于所有其他内核,则核心(SIMD或CPU)一次只能分配给1个内核(因为它们只有1台PC),即使它们可以同时运行1k个线程。在理想情况下,这会将您的OpenCL设备转换为少数核心(6-10)的池,这些核心串行消耗排队的内核。这就是假设API支持它和设备,但并非总是如此。在最坏的情况下,您将拥有一台运行单个内核的设备,并且99%的浪费。

可以在OpenCL中完成的事情示例:

  • 数据处理/处理。乘以向量,模拟粒子等。
  • 图像处理,边界检测,过滤等
  • 视频压缩,版本,代
  • 光线追踪,复杂光学数学等
  • 排序

不适合OpenCL的内容示例:

  • 主持异步请求(HTTP,流量,交互式数据)
  • 处理少量数据
  • 为每种类型处理需要完全不同处理的数据

从我的观点来看,使用多个内核的唯一真实用例是后者,无论你做什么,在这种情况下性能都会很糟糕。 更好地使用多线程池。