工作项执行顺序

时间:2013-07-07 22:44:46

标签: opencl gpgpu

我正在使用OpenCL。我感兴趣的是如何在以下示例中执行工作项。

我的一维范围为10000,工作组大小为512.内核是以下内容:

__kernel void
doStreaming() {
  unsigned int id = get_global_id(0);

  if (!isExecutable(id))
    return;

 /* do some work */
}

这里检查是否需要继续使用以下id的元素。

假设执行以第一个512大小的工作组开始,其中20个被isExecutable拒绝。 GPU是否继续执行其他20个元素而不等待前492个元素?

没有任何障碍或其他同步技术。

2 个答案:

答案 0 :(得分:2)

当一些工作项目远离通常/ *做一些工作* /时,他们可以通过从下一个wavefront(amd)或下一个warp(nvidia)获取指令来使用管道占用优势,因为当前warp / wavefront工作项目正忙着做其他事情。但这会导致内存访问序列化并清除工作组的访问顺序,从而降低性能。

避免使用不同的warp / wavefron :如果你在循环中执行if语句,那么它真的很糟糕,你可以找到另一种方式。

如果工作组中的每个工作项具有相同的分支,那么就可以了。

如果每个工作项在每百个计算中进行的分支很少,那就没关系。

尝试为所有工作项(为了实现并行数据/算法)生成相同的条件,以利用gpu带来的功能。

我知道摆脱最简单的branch-vs-compute情况的最佳方法是使用全局yes-no数组。 0 =是,1 =否:总是计算,然后将结果乘以工作项的yes-no元素。通常,每个核心添加1字节元素内存访问要比每个核心执行一次分支要好得多。实际上,在添加这个1字节后,使对象长度为2的幂可能会更好。

答案 1 :(得分:1)

是和否。以下详细说明基于NVIDIA的文档,但我怀疑它在ATI硬件上有什么不同(尽管实际数字可能有所不同)。通常,工作组的线程在所谓的warp中执行,warp是工作组大小的子块。在NVIDIA硬件上,每个工作组分为32个线程的warp。并且这些warp中的每一个都是以锁定步骤执行的,因此完全并行执行(它可能不是实时并行的,这意味着可能有16个并行线程,然后直接再次16个,但从概念上讲它们运行完全并行) 。因此,如果这32个线程中只有一个执行该附加代码,则其他线程将等待它。但是所有其他经线中的线程都不会关心这一切。

所以是的,可能会有不必要的线程等待其他线程,但这种情况发生的规模小于整个工作组的规模(任何NVIDIA硬件上都是32)。这就是为什么应该尽可能避免内部扭曲分支偏差的原因,这也是为什么保证在单个warp内工作的代码不需要任何同步的原因。共享内存访问(算法的常见优化)。