OpenCL 分支与内存冗余



我正在网格中处理项目,根据项目的类型,需要执行不同类型的计算/函数。但是我已经读到分支在做同样事情的工作项之间是一件非常糟糕的事情。为了规避这一点,我可以将网格拆分为每种类型的网格(在这种特殊情况下我只需要两个)......

在这种情况下,什么会更好;将分支留在那里,还是为每个类型制作两个网格?我知道这取决于分支内部发生的情况(计算边界)与网格的大小(内存/延迟限制)。

对于这类决定,是否有一些基本规则可以遵循,或者是否有共识,一般来说哪一个更好?

编辑:(空间)网格不像空间网格那样稀疏,而是一个结构(每个结构~200字节)的密集数组(没有空元素),最多可容纳约500.000个元素。

从另一个来源填充这个数组,使用该源我在那里放置三角形或线段。

然后使用此网格,我需要执行线段/线段或线段/三角形碰撞检测。所以问题是在这种情况下填充两个单独的数组(为了参数起见,假设 250.000 个元素 x 200 字节)并让工作项只对行/线或线/三角形进行批处理计算是否更有效。或者有一个 500.000x200 字节的大字节,并让每个工作项找出给定类型要执行的计算。

这取决于新网格的结构,也取决于旧网格的结构。

让我们采取最坏的情况。普通矩形网格(如图像)如果每个奇数项都是类型 1,每个偶数项都是类型 2。现在基本上一半的线程将在 GPU 中闲置(当 type1 被计算为 type2 线程"空闲"时)。这是因为工作组中的项目通常共享其程序计数器。

如果你的新网格是 2 个内核调用和简单的"不是 type2?返回",那么它比第一种情况更糟糕。但是,如果您设法制作 2 个网格,其中每个项目都是正确类型的,那么最好将其拆分。

如果您的原始网格是具有正好 2 半的图像,则可能无关紧要。只有边界内的组才会执行额外的工作。

树枝并没有那么邪恶。试想一下,只要你有一个分支,甚至工作组中的一个线程(或者你的硬件中的调度单位)采取与其他线程不同的方向,两个分支中的所有代码都将被带到任何地方。

这也是为什么优化(例如在某些特殊条件适用时不执行昂贵的计算)在 GPU 上通常不起作用的原因,因为如果其他线程没有满足条件,您仍然可以在每个线程中有效地计算它。

这没有一般规则,取决于具体情况。如果你写了很多代码,显然重新排列内存会更好。但是,如果您的分支只有 2 条指令,则不要重塑内存。

我将首先对每种类型(CPU 端或简单内核)的项目数量进行分类,并为每种类型的项目运行特定的内核。但是,这可能不适合您的情况。

如果您可以发布一些代码,也许我们可以为您指明正确的方向。

最新更新