仅在OpenCL内核中的缓冲区子集上操作

时间:2019-03-22 05:10:17

标签: opencl numerical-methods pyopencl

此处是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
}

还是有另一种/更适当的方法来实施此约束?

1 个答案:

答案 0 :(得分:0)

看起来足够了。

nPts-nGhostCells * 2点数的分支是相同的,并且如果nPts和nGhostCells是编译时常量,则可以预测。即使不可预测,足够大的nPts vs nGhostCells(1024 vs 3)也不应明显比零分支版本慢,除非“或”操作的等待时间。由于线程级并行性,即使“或”延迟也必须隐藏在阵列访问延迟之后。

在这些“中断”点,由于类似SIMD的体系结构以锁步方式运行,因此大多数16或32个线程将损失一些性能,并且仅在几个时钟周期内丢失。

如果您碰巧编写了一些混乱的分支,例如数据驱动的代码路径,则应将它们拆分为不同的内核(用于不同区域),或者在内核之前对它们进行排序,以使相邻线程之间的平均分支最小化。