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



我正在尝试运行向量加法的应用程序,其中我需要同时启动多个内核,因此,对于并发内核启动,我最后一个问题中有人建议我使用多个命令队列。它是由阵列定义的

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循环来启动内核,同时也使用排队数据

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

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

我也读了你的最后一个问题,我认为你应该首先重新思考你真正想做什么,以及OpenCL是否真的是这样做的方式。

OpenCL是一个用于masive并行处理和数据处理的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模型。事实上,in可能比CPU单个线程慢得多

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

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

  • 数据处理。相乘矢量、模拟粒子等
  • 图像处理、边界检测、滤波等
  • 视频压缩、编辑、生成
  • 光线跟踪、复杂灯光数学等
  • 排序

不适合OpenCL的东西的例子:

  • 正在终止异步请求(HTTP、trafic、交互式数据)
  • 处理少量数据
  • 处理每种类型都需要完全不同处理的数据

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

最新更新