这里是OpenCL的新手。我正在尝试将我写入OpenCL的数值方法转换为加速。我正在使用PyOpenCL软件包,因为我已经用Python编写了一次,据我所知,使用C版本没有令人信服的理由。不过,如果我错了,我会全力以赴。
我已经设法将我需要的大部分功能转换为OpenCL内核。我的问题是如何(正确)告诉OpenCL忽略我的边界/鬼细胞。我需要这样做的原因是我的方法(例如)点i
访问[i-2:i+2]
的单元格,所以如果i=1
,我将运行数组的末尾。所以 - 我添加一些额外的点来防止这种情况,然后告诉我的算法只运行点[2:nPts-2]
。很容易看到如何使用for
循环来做到这一点,但我对于为内核执行此操作的“正确”方法有点不清楚。
是否足够做,例如(伪代码)
__kernel void myMethod(...) {
gid = get_global_id(0);
if (gid < nGhostCells || gid > nPts-nGhostCells) {
retVal[gid] = 0;
}
// Otherwise perform my calculations
}
或者是否有其他/更合适的方法来强制执行此约束?
看起来足够了。
对于nPts-nGhostCells * 2个点,分支是相同的,如果nPts和nGhostCell是编译时常量,则可以预测。即使它是不可预测的,除了“或”操作的延迟之外,足够大的nPts与nGhostCells(1024 vs 3)不应该明显慢于零分支版本。由于线程级并行性,即使“或”延迟也必须隐藏在数组访问延迟之后。
在那些“中断”点,由于SIMD类似架构的锁步运行,大多数16或32个线程将失去一些性能并且仅在几个时钟周期内。
如果您碰巧编写了一些混乱的分支,比如数据驱动的代码路径,那么您应该将它们分成不同的内核(针对不同的区域),或者在内核之前对它们进行排序,以便最小化相邻线程之间的平均分支。