如何避免在OpenCL中回读

时间:2012-07-20 19:39:09

标签: opencl

我正在使用OpenCL实现一个算法。我将多次循环使用C ++并每次调用相同的OpenCL内核。内核将生成下一次迭代的输入数据和这些数据的数量。目前,我在每个循环中读回这个数字两个用法:

  1. 我使用这个数字来决定下一个循环需要多少工作项;和
  2. 我使用此数字来决定何时退出循环(当数字为0时)。
  3. 我发现读数占用了循环的大部分时间。有什么方法可以避免吗?

    一般来说,如果需要重复调​​用内核,并且退出条件依赖于内核生成的结果(不是固定数字循环),那么如何有效地执行呢?有没有像OpenGL中的遮挡查询那样你可以做一些查询而不是从GPU回读?

3 个答案:

答案 0 :(得分:2)

从GPU内核读回一个数字总是需要10s - 1000s微秒或更长时间。

如果控制号始终在减少,您可以保留在全局内存中,并根据全局ID对其进行测试,并确定内核是否在每次迭代时都有效。使用全局内存屏障来同步所有线程...

kernel void x(global int * the_number, constant int max_iterations, ... )
{
    int index = get_global_id(0);
    int count = 0;    // stops an infinite loop

     while( index  < the_number[0] && count < max_iterations )
     {
      count++;
      // loop code follows

      ....

      // Use one thread decide what to do next 
      if ( index  == 0 )
      {
          the_number[0] = ... next value
      }

      barrier( CLK_GLOBAL_MEM_FENCE ); //  Barrier to sync threads
    }
}

答案 1 :(得分:1)

你有几个选择:

  1. 如果可能,您只需将循环和条件移动到内核中即可?使用其他工作项不执行任何操作的方案,具体取决于当前迭代的输入。
  2. 如果无法实现1.我建议您将“决策”内核生成的数据存储在缓冲区中,并使用该缓冲区“指导”其他内核。
  3. 这两个选项都允许您跳过回读。

答案 2 :(得分:0)

我刚刚完成一些研究,我们必须解决这个问题!

我们发现了一些事情:

  1. 使用两个(或更多)缓冲区!进行内核的第一次迭代 对b1中的数据进行操作,然后对b2进行操作,然后再对b1进行操作。在 在每次内核调用之间,读回另一个缓冲区的结果 并检查是否是时候停止迭代了。当内核花费的时间超过读取时,效果最佳。使用分析工具确保您不等待读取(如果是,请增加缓冲区数量)。

  2. 过度拍摄!为每个内核添加一个完成检查,然后调用它 在复制数据之前几次(100s)次。如果你的内核是 低成本,这可以很好地工作。