确定 OpenCL 工作组规模的限制因素?

Nic*_*rca 3 opencl mali

我正在尝试在资源较少的嵌入式 GPU 上运行一些为桌面显卡编写的 OpenCL 内核。特别是,桌面版本假设始终支持至少 256 的工作组大小,但基于 Mali T628 ARM 的 GPU 仅保证 64+ 的工作组大小。

事实上,一些内核报告CL_KERNEL_WORK_GROUP_SIZE只有 64,我不知道为什么。我检查了CL_KERNEL_LOCAL_MEM_SIZE有问题的内核,它是 <2 KiB,而CL_DEVICE_LOCAL_MEM_SIZE32 KiB,所以我想我可以排除__local存储。

还有哪些其他因素(例如,寄存器/__private内存?)导致 low CL_KERNEL_WORK_GROUP_SIZE,我如何检查使用情况?我对程序化内省(例如clGetKernelWorkGroupInfo()我已经做过一些)以及我可能不知道的任何开发工具都持开放态度。

编辑:

内核是 OpenCV 的 OpenCL v2.4 模块的一部分。特别是,内核icvCalcOrientationsurf.cl. 代码相当复杂,并且设置了多个编译时参数,这就是为什么手动分析内核以查找问题而不提示要查看的内容有点不可行的原因。

如果有办法在 NVidia 或 AMD 硬件(我可以访问)上解决此问题,我愿意接受。

Bai*_*aiz 5

编辑

由于我之前的答案显然是错误的,因此我需要有关该问题的更多信息。

通过说“某些内核报告 CL_KERNEL_WORK_GROUP_SIZE 仅为 64”,您暗示内核存在于更大的工作组大小可用的地方。是这样吗?如果不是,那么不幸的是,该设备根本无法支持超过 64 个工作项。

请您设置所有内核参数后和执行内核之前查询内核中设备的所有可用信息。要查询的参数(主要取自 ( Source ) )是

  • CL_DEVICE_GLOBAL_MEM_SIZE
  • CL_DEVICE_LOCAL_MEM_SIZE
  • CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE
  • CL_DEVICE_MAX_MEM_ALLOC_SIZE
  • CL_DEVICE_MAX_WORK_GROUP_SIZE
  • CL_DEVICE_MAX_WORK_ITEM_SIZES
  • CL_KERNEL_WORK_GROUP_SIZE
  • CL_KERNEL_LOCAL_MEM_SIZE
  • CL_KERNEL_PRIVATE_MEM_SIZE 可能还有更多,但目前没有想到。

一般信息:

由于本地内存有限,因此可以限制工作组的大小。如果您有一个使用大量私有内存的内核,则可以达到此限制(“大量”是一个相对术语 - 在较弱的硬件上,即使看似很少的变量也可能达到这一限制)。“然而,这个限制只是在理想条件下。如果您的内核每个 WG 使用大量 WI,那么一些私有 WI 数据可能会溢出到本地内存。[...]”(来源)。

因此,其中一些私有内存可能会在您没有意识到的情况下交换到本地内存,因此使用的本地内存的累积大小和交换的私有内存所需的大小大于可用的本地内存大小。

CL_DEVICE_LOCAL_MEM_SIZE返回本地内存的可用大小,CL_KERNEL_LOCAL_MEM_SIZE告诉您使用了多少本地内存。显然,这也通过查看 clSetKernelArg 考虑了动态本地内存,但是我不确定如果您查询CL_KERNEL_LOCAL_MEM_SIZE before设置内核参数(这是您想要做的事情以确定本地内存的大小),这应该如何工作。 ..)

无论如何,OpenCL 确切地知道您使用了多少本地内存,因此它可以计算它可以支持多少个工作项(每个工作项都有可能需要交换到本地内存的私有内存)。这种减少的本地工作大小可能是您在查询时得到的CL_KERNEL_WORK_GROUP_SIZE

查看您发布的内核后,我认为本地内存不是这里的问题(这是您已经怀疑的),特别是因为您只使用了 32 KiB 本地内存中的 2 个。