OpenCL中全局工作量是否需要是工作组大小的倍数?

时间:2010-06-30 09:24:24

标签: matrix gpu opencl gpgpu

您好:OpenCL中全局工作量(维度)是否需要是工作组大小(维度)的倍数?

如果是这样,是否有一种处理矩阵的标准方法而不是工作组维度的倍数?我可以想到两种可能性:

将工作组维度的大小动态设置为全局工作维度的因子。 (这会产生查找因子的开销,并可能将工作组设置为非最佳大小。)

将全局工作的维度增加到工作组维度的最接近倍数,保持所有输入和输出缓冲区相同但检查内核中的边界以避免segfaulting,即对工作项不做任何操作期望的输出。 (这似乎是更好的方式。)

第二种方式有效吗?有没有更好的办法? (或者它是否没有必要,因为工作组维度不需要划分全球工作维度?)

谢谢!

3 个答案:

答案 0 :(得分:7)

链接Chad的Thx。但实际上,如果您继续阅读:

  

如果指定了local_work_size,则   global_work_size [0],... global_work_size [work_dim - 1]中指定的值必须均匀   可以被local_work_size [0]中指定的相应值整除,...   local_work_size [work_dim - 1]。

是的,本地工作规模必须是全球工作规模的倍数。

我还认为将全局工作大小分配到最接近的倍数并注意边界应该有效,我会在我试用它时发表评论。

答案 1 :(得分:1)

根据标准,它不一定是我所看到的。我想我会用分支来处理它,但我不知道你正在做什么样的矩阵运算。

http://www.khronos.org/registry/cl/specs/opencl-1.1.pdf#page=131

  

global_work_size指向一个数组   work_dim无符号值的   描述全球的数量   work_dim维度中的工作项   将执行内核函数。该   全球工作项的总数是   计算为global_work_size[0] *   ...... * global_work_size[work_dim – 1]

     

中指定的值   global_work_size +对应   global_work_offset中指定的值   不能超过给出的范围   设备上的sizeof(size_t)   内核执行将是什么   入队。 sizeof(size_t)表示   设备可以使用确定   表4.3中的CL_DEVICE_ADDRESS_BITS。   例如,如果   CL_DEVICE_ADDRESS_BITS = 32,即   该设备使用32位地址   空格,size_t是32位无符号   整数和global_work_size值   必须在1 .. 2 ^ 32 - 1的范围内。   超出此范围的值返回a   CL_OUT_OF_RESOURCES错误。

答案 2 :(得分:1)

这似乎是一篇旧帖子,但让我用一些新信息更新这篇文章。希望它可以帮助别人。

  

全局工作规模(维度)是否需要是工作组的倍数   OpenCL中的大小(尺寸)?

答案:真正的OpenCL 2.0。在CL2.0之前,您的全局工作大小必须是本地工作大小的倍数,否则在执行clEnqueueNDRangeKernel时将收到错误消息。

但是从CL2.0开始,这不再是必需的了。您可以使用适合您的应用程序维度的任何全局工作大小。但请记住,硬件实现可能仍然使用" old"方式,这意味着填充全局工作组大小。因此,它使性能高度依赖于硬件架构。您可能会在不同的硬件/平台上看到完全不同的性能。此外,您希望使您的应用程序恢复兼容,以支持仅支持1.2版本的CL的旧平台。因此,我认为CL2.0中添加的这个新功能只是为了便于编程,以获得更好的可控性能和向后兼容性,我建议您仍然使用以下提到的方法:

  

将全局工作的维度增加到最接近的倍数   工作组维度,保持所有输入和输出缓冲区   相同但检查内核中的边界以避免segfaulting,即do   没有关于工作项超出所需输出的约束。 (这个   似乎是更好的方式。)

答案:你是对的。这是处理此类案件的正确方法。仔细设计本地工作组大小(考虑诸如寄存器使用,缓存命中/未命中,内存访问模式等因素)。然后将您的全局工作大小填充到本地工作大小的倍数。然后,你很高兴。

另一件需要考虑的事情是,如果内核中有很多边界检查工作,您可以利用图像对象来存储数据而不是缓冲区。对于图像,边界检查由硬件自动完成,在大多数实现中几乎没有开销。因此,填充全局工作大小,将数据存储在图像对象中,然后,您只需要正常编写代码而不必担心边界检查。