c++ - 在单个阵列上的 opencl 中处理工作组及其大小

标签 c++ arrays opencl gpgpu

我正在使用 OpenCL C++ 来实现我的项目。我想从我的 GPU/s 中获得最大速度/性能(取决于我有多个 GPU 还是单个 GPU)。但出于这个问题的目的,让我们假设我只有一台设备。

假设我有一个长度为 100 的数组。

double arr[100];

现在我正在做的是通过以下方法调用内核。

kernelGA(cl::EnqueueArgs(queue[iter],
                         cl::NDRange(100)),
                         d_arr, // and some other buffers.
         )

现在在内核端。我有一个全局 ID。即:

int idx = get_global_id(0);

我希望我的内核工作的方式如下:

  • 100 个工作组中的每个工作组将分别处理一个要素。
  • 每个工作组都使用一些规则来更新数组的元素。例如:

    if (arr[idx] < 5) {
        arr[idx] = 10; // a very simple example.
    }
    

对于大多数部分来说,没关系。但是有一点我想交换,我希望线程/工作项相互通信。在这一点上,他们似乎没有工作,他们似乎没有沟通。

例如:

if(arr[idx] < someNumber) {
    arr[idx] = arr[idx + 1];
}

此时,似乎没有任何效果。我试图实现一个 for 循环并创建一个障碍

barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);

但它也不起作用。它不会更改数组元素的值。

我有以下问题:

1. 为什么不起作用?我的实现有误吗?线程似乎正确地更新了它们自己的索引数组元素。但是当涉及到它们之间的通信时,它们不起作用。为什么?

2. 是我实现的障碍和只让一个工作项目出错了吗?有没有更好的方法让一个项目处理这部分,而其他项目等待这个完成?

最佳答案

你写的代码是串行的:

if(arr[idx] < someNumber) {
   arr[idx] = arr[idx + 1];
}

worker N 将取 worker N-1 的结果,N-1 取 N-2 的结果,依此类推。 所以这意味着 worker N 需要等待所有其他人完成。这意味着代码不是并行的,而且永远不会。使用 CPU 比使用 GPU 的计算效果要好得多。

OpenCL 设计模型,允许您并行运行多个工作项,但同步模型只允许在工作组内同步。 如果您需要全局同步,则表明您的算法不适用于 OpenCL。


现在,如果我假设您只需要最后一个元素的值。而您真正想要的是对所有数组执行“求和”。那么,这是一个归约问题,可以通过这种方式并行化在 log(N) 时间内执行:

1st step,   array[x] = array[x] + array[N/2+x] (x from 0 to N/2)
2nd step,   array[x] = array[x] + array[N/4+x] (x from 0 to N/4)
...
log(N) passes

每个步骤都将是一个单独的内核,因此确保在开始下一批之前所有工作项都已完成。

另一个更快的选择是在工作组内部执行缩减,因此如果工作组大小为 256,您可以在每次通过时将 256 个组加在一起。这比每次通过减少 2 更快。

关于c++ - 在单个阵列上的 opencl 中处理工作组及其大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42581203/

相关文章:

c++ - 使用语言特性(不是预处理器指令)在 C++ 中自动生成大括号括起来的初始化列表

JavaFX 初始化 TextField 数组

parallel-processing - FPGA 中的 Altera OpenCL 并行执行

opencl - OpenCL 中目标平台的示例是什么?

floating-point - OpenCL 归约中 min() 和 max() 的中性元素

c++ - 运算符==比较两个不同的类

c++ - 寻找C++区间树算法实现

c++ - WASAPI 环回 : Save wave file

java - 如何将字节的json数组转换为位图

python - 将列表转换为 numpy 数组