2

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

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 循环时,只需手动定义多个命令队列,它就可以正常工作。

4

1 回答 1

3

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

OpenCL 是用于大规模并行处理和数据处理的 API。每个内核(或排队的任务)同时对许多数据值进行并行操作,因此性能优于任何串行 CPU 处理多个数量级。

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

但是并发从来都不是必需的。(否则单核CPU就无法执行任务,绝不会这样。会慢一些,好吧,但还是可以运行的)

即使需要同时运行 2 个任务。所用时间是否相同:

非并发案例:

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 单线程慢。

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

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

  • 数据处理/处理。向量相乘,模拟粒子等。
  • 图像处理、边界检测、过滤等
  • 视频压缩、编辑、生成
  • 光线追踪、复杂的光数学等。
  • 排序

不适合 OpenCL 的示例:

  • 处理异步请求(HTTP、流量、交互式数据)
  • 处理少量数据
  • 处理需要对每种类型进行完全不同处理的数据

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

于 2014-10-10T16:01:18.150 回答