这似乎是一个旧帖子,但让我用一些新信息更新这个帖子。希望它可以帮助其他人。
全局工作大小(维度)是否需要是 OpenCL 中工作组大小(维度)的倍数?
答:在 OpenCL 2.0 之前都是如此。在CL2.0之前,你的全局work size必须是local work size的倍数,否则你在执行clEnqueueNDRangeKernel时会报错。
但是从 CL2.0 开始,这不再是必需的了。您可以使用适合您的应用程序尺寸的任何全局工作大小。但是,请记住,硬件实现可能仍然使用“旧”方式,这意味着填充全局工作组大小。因此,它使性能高度依赖于硬件架构。您可能会在不同的硬件/平台上看到完全不同的性能。另外,您想让您的应用程序向后兼容,以支持仅支持 CL 至 1.2 版本的旧平台。所以,我认为CL2.0中加入的这个新特性只是为了方便编程,为了获得更好的可控性能和向后兼容性,我建议你还是使用你提到的以下方法:
将全局工作的维度增加到工作组维度的最接近倍数,保持所有输入和输出缓冲区相同,但检查内核中的边界以避免段错误,即对超出所需输出范围的工作项不做任何事情. (这似乎是更好的方法。)
答:你完全正确。这是处理这种情况的正确方法。仔细设计本地工作组大小(考虑寄存器使用情况、缓存命中/未命中、内存访问模式等因素)。然后将您的全局工作大小填充到本地工作大小的倍数。然后,你可以走了。
要考虑的另一件事是,如果您的内核中有很多边界检查工作,您可以利用图像对象而不是缓冲区来存储数据。对于图像,边界检查由硬件自动完成,在大多数实现中几乎没有开销。因此,填充您的全局工作大小,将数据存储在图像对象中,然后,您只需要正常编写代码而无需担心边界检查。