Synchronization OpenCL,工作组中工作项的同步执行(非屏障和内存提取)

Synchronization OpenCL,工作组中工作项的同步执行(非屏障和内存提取),synchronization,opencl,gpu,memory-barriers,Synchronization,Opencl,Gpu,Memory Barriers,@大家好 我正在用OpenCL在AMD GPU上实现数字滤波器。 过滤器的功能是相邻元素之间的依赖关系。 每个元素取决于左侧、顶部和右上角的元素。 请查看w/图像,以使其更好 这样, 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 et

@大家好

我正在用OpenCL在AMD GPU上实现数字滤波器。 过滤器的功能是相邻元素之间的依赖关系。 每个元素取决于左侧、顶部和右上角的元素。 请查看w/图像,以使其更好

这样,

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个元素执行,那么一些行可能会并行执行

所以,我来问一个问题,如何组织元素之间的同步??? 我没有找到任何方法来组织工作组内的同步。 屏障似乎不是合适的机制,因为它们是用来组织同步存档检查点的,而在我的例子中,它必须是线程之间的同步w/延迟

有一种方法似乎是合适的。使用clEnqueueTask和events或clenqueueendrangekernel w/workgroup是相等的。 但在这种情况下,我不能使用本地内存,它将大大减慢

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

提前谢谢。 请注意, -这个6x4的尺寸仅用于说明,实际上它大约是4K元素。
-元素是8x8整型值块。

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

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性能。并非所有线程都同时运行,因此您永远不会对设备的全部容量充电


我希望我理解你的问题。对于更好的解决方案,算法的附加信息将非常有用。

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

因为通常数字滤波器只需要和输入数据交互以提供输出。但它们不会递归地使用前一项或相邻项的输出

如果是这样,您根本不需要任何同步机制

在所有OpenCL指南中都应该有一个很大的免责声明:本地内存很快,但是私有内存更快,如果您不需要使用本地内存,因为您不需要在线程之间同步,那么就不要使用它

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

如果你还想走那条路。然后,您必须在内核中执行两个部分:获取和过滤。每一部分都由屏障隔开

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


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

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


从你的问题描述中,我不能完全理解任何给定的工作项似乎都依赖于所有先前工作项的某个子集,包括当前工作组之外的一些工作项。如果这是真的,你有一个顺序问题,而不是并行问题。如果是这种情况,您需要找出如何通过删除或至少减少这些依赖关系将其转化为并行问题。例如,您能否将回望量限制为不大于某个数字?如果是这样,您可以并行计算相隔很远的项,而无需依赖项。或者,您可以并行处理不同的问题集,每个问题集只处理一个工作项,但许多问题是并行处理的。

谢谢您的回复。但是,在我询问同步并行线程时,如何提供这些障碍是完全序列化执行的方法。是的,6x4阵列仅用于说明,实际上它是2K x 2K阵列…目前我不确定我是否理解你的问题
完全正确。在同步工作组内的并行线程时会提到障碍,您可以使用它来同步并行线程。我认为您的目标是实现一种序列化执行,以确保当前元素的所有依赖项在计算时都得到满足。不,问题是如何并行组织执行,允许某些依赖项。序列化不是问题。请看下面的评论,我试图再次解释。希望有点清楚。对于第一个问题-是的,是的。当然,除边界外的每个项都使用其相邻项的过滤输出值。需要同步。我想使用精确的本地内存来避免从全局内存中二次读取输入数据。请注意,元素是8x8整型块,而不仅仅是int或float。在这种情况下,您的问题无法使用OpenCL解决。至少不是以一种有效的方式。因为您的问题主要是串行的。依赖性…,包括当前工作组之外的一些-是的,有,但工作组的sych是另一项任务。让我们暂且不谈,假设工作组是独立的。同样,行中的每个元素都是逐个计算的,行中的元素只按顺序计算。但行可以并行计算,并考虑至少完成上述行的2个元素。例如,当第0行的0-4完成时,可能会计算第1行的元素0-3。或第3行的元素0-当第2行的元素0-1完成时,依此类推。