在单个数组中与工作组及其大小合作
Working with work groups and their sizes in opencl on a single array
我正在使用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. }
对于大多数零件,都可以。但是,我想互换一个点,以及我希望线程/工作项目相互通信的地方。到那时,它们似乎不起作用,并且似乎没有交流。
eg:
if(arr[idx] < someNumber) {
arr[idx] = arr[idx + 1];
}
在这一点上,似乎没有任何作用。我试图实现循环并创建障碍
barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);
,但也行不通。它不会更改数组元素的值。
我有以下问题:
1。为什么不起作用?我的实施错误吗?这些线程似乎正确更新了自己的索引数组元素。但是,当他们之间的交流时,它们不起作用。为什么?
2。我的障碍实现,只让一个工作项目错误吗?有没有更好的方法让一个项目在等待此部分完成此部分?
您编写的代码是序列的:
if(arr[idx] < someNumber) {
arr[idx] = arr[idx + 1];
}
工人n将取得n-1,n-1的结果,n-2的结果,依此类推。因此,这意味着工人n需要等待所有其他人完成。这意味着代码不平行,永远不会。使用CPU比GPU要好得多。
OpenCL设计模型,允许您并行运行多个工作项目,但是同步模型仅允许在工作组内同步。如果您需要全局同步,则明确表明您的算法不适合Opencl。
现在,如果我假设您只需要最后一个元素的值。您真正想要的是执行所有数组的"总和"。然后,这是一个减少问题,可以通过这种方式并行化在日志(n)时间(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。
我怀疑您的问题代表了一个并行能力有限的问题,因此适合任何类型的GPGPU解决方案。
考虑以下元素数组:
1 5 2 6 5 3 6 7 2 8 1 8 3 4 2
现在假设我们对此数据执行以下转换:
//A straightforward, serially-executed iteration on the entire array.
for(int i = 0; i < arr.size() - 1; i++) {
if(arr[i] < 5) arr[i] = arr[i + 1];
}
结果将为
5 5 6 6 5 6 6 7 8 8 8 8 4 2 2
但是,如果for循环反向执行会发生什么?
for(int i = arr.size() - 2; i >= 0; i--) {
if(arr[i] < 5) arr[i] = arr[i + 1];
}
结果将为
5 5 6 6 5 6 6 7 8 8 8 8 2 2 2
请注意,根据执行顺序,第三到持久的数字有何不同。我的示例输入不会发生太大的变化,但是如果您的代码在所选阈值以下的数字大多数,则可以完全更改整个数组!因为GPGPU API不能保证单个工作项目的执行顺序,这意味着您的执行顺序可以像我写的第一个循环的for 一样,或者它可以可以就像我写的第二个循环一样,或者可以是一个完全随机的订单 - 您已经编写了非确定性代码,而使其确定性的唯一方法是使用SO SO SO SO SO您要保证顺序排序的许多障碍,在这一点上,没有理由首先使用GPGPU API。
您可以写下类似以下内容,这是确定性的:
if(arr[i] < 5) output[i] = arr[i + 1];
else output[i] = arr[i];
,但这可能需要重新考虑您的设计约束。我不知道,因为我不知道您的程序最终会在做什么。
无论哪种方式,您都需要花一些时间重新考虑您实际尝试做的事情。
- 如何将一个ostringstream十六进制字符串字符对转换为单个unit8t等价的二进制值
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- Eclipse CDT:单个项目中有多个C++文件
- 为什么我们将单个或多维数组的大小声明为常量值?
- C++调用具有 *this 属性的单个帮助程序函数
- 如何读取单个字符并在输入两个字符序列时输出? 使用 while 循环和C++
- 如何将可变参数模板转换为多个单个模板?(C++竞争编程调试模板)
- 将多个 for 循环组合成单个迭代器
- 如何将多种语言设置放在单个 .clang 格式文件中
- QT QOpenGLWidget:如何在不使用数据块复制的情况下修改VBO中的单个顶点值?
- 在 c++ 中对单个排序数组中的 2 个未排序数组进行排序
- 与多个 for 循环与单个 for 循环 wrt 相关的性能从多映射获取数据
- C++:如何用单个命令替换复杂的迭代?
- C++单个生成文件多个二进制文件
- 将单个未唱的 int 发送到 VBO
- 如何限制在C++中为单个类创建的对象数量?
- 在C++中使用线程查找友好号码比单个线程花费更多时间
- 从unordered_map中删除单个节点
- 通过命令行在Visual Studio中编译单个独立文件
- 在单个数组中与工作组及其大小合作