OpenCL,工作组中工作项的同步执行(不是障碍和内存提取)

时间:2013-12-21 07:48:28

标签: synchronization opencl gpu memory-barriers

@大家好,

我正在通过OpenCL在AMD GPU上实现数字滤波器。 过滤器的功能是相邻元素之间的依赖关系。 每个元素都依赖于左侧,顶部和右上角的元素。 请参阅LINK w / image以使其更好。

这样,

element 2 -> from 1.
element 3 -> from 2.
element 7 -> from 1, 2 (top, top-right).
element 8 -> from 7, 2, 3.
element 16 -> from 15, 10, 11 
etc... applying for each element from 2nd to 24th

如果上面的行前面有2个元素,那么总共可以并行执行几行。

所以,我提出了一个问题,如何组织元素之间的同步??? 我没有找到任何方法来组织工作组内的同步。 障碍似乎不是合适的机制,因为它们要组织同时存档检查点,而在我的情况下,它必须是线程之间的延迟同步。

有一种方式似乎是合适的。使用clEnqueueTask()和事件(或clEnqueueNDRangeKernel w / workgroup等于< 1,1,1>)。 但在这种情况下,我无法使用本地内存,而且速度会明显变慢。

再次提问:如何在同一工作组中的线程之间组织同步以有效使用快速本地内存???

提前致谢。
请注意,
- 6x4尺寸仅用于说明,实际上它与4K元素有关 - “element”是8x8整数值块。

3 个答案:

答案 0 :(得分:0)

只要您的工作项总数适合单个工作组,您就可以通过使用障碍来解决这种依赖关系。详细地说,您必须为每个依赖项同步工作组中的所有工作项。这可以通过通过其全局索引识别作为线程运行的每个元素来完成。

element 2 -> from 1.
BARRIER -------------------------------------------(SYNC WG)
element 3 -> from 2.
BARRIER -------------------------------------------(SYNC WG)
element 7 -> from 1, 2 (top, top-right).
BARRIER -------------------------------------------(SYNC WG)
element 8 -> from 7, 2, 3.
BARRIER -------------------------------------------(SYNC WG)
element 16 -> from 15, 10, 11.

当涉及到不适合您的工作组维度的更大数据集时,您可能必须使用其他内核和缓冲区。您还必须担心其依赖性超出特定工作组边界的元素。在这种情况下,只能通过使用其他内核来实现全局同步。参见示例,元素分布在不同的工作组中。

.____WG1_____.____WG2_____.____WG3_____.____WG4_____.
|           2|3           |            |            |
|           7|            |            |            |
|            |            |            |            |
|____________|____________|____________|____________|
|            |            |            |            |
|            |            |            |            |
|            |            |            |            |
|____WG5_____|____WG6_____|____WG7_____|____WG8_____|

但主要问题是:您的算法及其依赖性会导致非常糟糕的SIMD性能。并非所有线程都同时运行,因此您永远不会收取设备的全部容量。

我希望我理解你的问题。为了更好的解决方案,您的算法的其他信息将非常有用。

答案 1 :(得分:0)

第一个问题是:“每个工作项是否需要与其他工作项同步?”

由于数字滤波器通常只需要与输入数据交互以提供输出。但是它们不会递归地使用前一个或邻近项的输出。

如果是这种情况,则根本不需要任何同步机制。

所有OpenCL指南中都应该有一个BIG免责声明:“本地内存很快但私有内存更快,如果你不需要使用本地内存,因为你不需要在线程之间同步,然后根本就不要使用它。“

在过滤的特定情况下,可能是相邻单元需要与输入值相同的存储区的情况。如果是这种情况,最好在本地保存它并避免一些全局提取。由于您的算法只需要3个值,因此您的重用因子仅为2/3。但考虑到当地储蓄过程的额外开销,我不希望从中获得重大利益。

如果你还想走那条路。然后你必须在你的内核中做两部分:获取和过滤。每个部分由障碍物隔开。

在第一部分中,您需要将本地内存复制到工作组所需的区域。这与一些部分与其他工作组重叠(我之前说过的开销)。

然后在读取内存后,在第二步中,您只需处理过滤器并返回结果。无需同步最后一部分,因为每个项目只会影响一个输出值。

答案 2 :(得分:0)

OpenCL只能在工作组内同步,而不能跨工作组同步。如果需要后者,请排队顺序内核。

从您的问题描述(无可否认,我不是完全理解),听起来任何给定的工作项都依赖于所有先前工作项的某些子集,包括当前工作之外的一些组。如果确实如此,则会出现顺序问题,而不是并行问题。如果是这种情况,您需要通过删除或至少减少这些依赖关系来弄清楚如何将其转变为并行问题。例如,您可以将“回顾”的数量限制为不超过某个数字吗?如果是这样,您可以并行计算远离而没有依赖关系的项目。或者,也许你可以并行处理不同的问题集(只做一个工作项,但很多并行)。