如何避免OpenCL中的常量内存复制

时间:2016-11-19 20:04:20

标签: c++ multithreading opencl

我编写了C ++应用程序,它模拟了简单的热流。它使用OpenCL进行计算。 OpenCL内核采用二维( n x n )温度值数组及其大小( n )。它会在每个循环后返回带有温度的新数组:

伪代码:

int t_id = get_global_id(0);
if(t_id < n * n)
{
    m_new[t_id / n][t_id % n] = average of its and its neighbors (top, bottom, left, right) temperatures
}

正如您所看到的,每个线程都在计算矩阵中的单个单元格。当主机应用程序需要执行X计算周期时,它看起来像这样

  • 1 ... X
    1. 将内存复制到OpenCL设备
    2. 调用内核
    3. 将内存复制回来

我想重写内核代码来执行所有X周期,而无需对OpenCL设备进行常量内存复制。

  1. 将内存复制到OpenCL设备
  2. 调用内核X次或调用内核一次并使其计算X周期。
  3. 将内存复制回来
  4. 我知道内核中的每个线程都应该在所有其他线程正在执行其工作时锁定,之后 - m [] []和m_new [] []应该被交换。我不知道如何实现这两个功能中的任何一个。

    或许还有另一种方法可以做到最佳?

1 个答案:

答案 0 :(得分:1)

Copy memory to OpenCL device
Call kernel X times
Copy memory back
这是有效的。确保call kernel没有阻塞(因此每个周期保存1-2毫秒)并且没有任何主机可访问的缓冲区属性,例如USE_HOST_PTR或ALLOC_HOST_PTR。

如果调用内核X次并没有获得满意的性能,你可以尝试使用单个工作组(例如只有256个线程)循环X次,每个循环最后有一个barrier(),所以所有256个线程在启动前同步下一个周期。通过这种方式,您可以在M是计算单元(或工作组)的数量的同时计算M个不同的热流问题,如果它是服务器,它可以提供许多计算。

无法进行全局同步,因为在启动最新线程时,第一个线程已经消失。它同时使用(计算单元数)(每个工作组的线程数)(每个工作组的波前数)线程。例如,一个具有5个计算单元和本地范围= 256的R7-240 gpu,它一次可以运行5 * 256 * 20 = 25k个线程。

然后,为了进一步提高性能,您可以应用本地内存优化。