如何避免OpenCL中的常量内存复制 我编写了C++程序,模拟简单的热流。它使用OpenCL进行计算。 OpenCL内核采用二维(nxn)温度值数组及其大小(n)。它会在每个循环后返回带有温度的新阵列:

如何避免OpenCL中的常量内存复制 我编写了C++程序,模拟简单的热流。它使用OpenCL进行计算。 OpenCL内核采用二维(nxn)温度值数组及其大小(n)。它会在每个循环后返回带有温度的新阵列:,c++,multithreading,opencl,C++,Multithreading,Opencl,伪代码: 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 } int t_id=get_global_id(0); 如果(t_id设置参数(0,A);3) 运行内核时:enqueueNDRangeKernel(…);我已经在我的代码中

伪代码:

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
}
int t_id=get_global_id(0);
如果(t_id
如您所见,每个线程都在计算矩阵中的单个单元。当主机应用程序需要执行X个计算周期时,它看起来是这样的

  • 对于1。。。X
  • 将内存复制到OpenCL设备
  • 调用内核
  • 复制内存
我想重写内核代码,以执行所有X周期,而无需在OpenCL设备上不断复制内存

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

    或者也许有另一种方法可以达到最佳效果

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

    如果调用内核X次不能获得令人满意的性能,您可以尝试使用单个工作组(例如仅256个线程)循环X次,使每个周期结束时都有一个barrier(),以便所有256个线程在开始下一个周期之前同步。通过这种方式,您可以同时计算M个不同的热流问题,其中M是计算单元(或工作组)的数量。如果这是一个服务器,那么它可以处理这么多计算

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


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

    您能再为我澄清一件事吗?内存何时实际复制到OpenCL设备?1) 创建缓冲区时:缓冲区A(上下文、CL_MEM_COPY_HOST_PTR、大小、MEM);2) 设置内核参数时:内核->设置参数(0,A);3) 运行内核时:enqueueNDRangeKernel(…);我已经在我的代码中做了一些测量,但我仍然不清楚。没有一个。它是在队列刷新后,gpu开始发出队列后,以及在enqueuewritebuffer命令完成之前复制的。假设所有命令都是非阻塞类型。如果将enqueuewritebuffer设置为blocking,则在退出该enqueuewritebuffer函数之前完成缓冲区的复制。clFinish()为队列创建一个开始信号,使其全部开始。clFinish()是同步主机和设备以确保队列是否完成的最简单方法。但是,实现可能会让命令立即异步启动,您可能需要在顶部放置一个用户事件处理程序