【问题标题】:Determine limiting factor of OpenCL workgroup size?确定 OpenCL 工作组规模的限制因素?
【发布时间】:2015-01-20 09:33:48
【问题描述】:

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

确实,一些内核报告CL_KERNEL_WORK_GROUP_SIZE 只有 64 个,我不知道为什么。我检查了CL_KERNEL_LOCAL_MEM_SIZE 的相关内核,它是CL_DEVICE_LOCAL_MEM_SIZE 是32 KiB,所以我想我可以排除__local 存储。

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

编辑:

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

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

【问题讨论】:

  • 您的内核是使用动态本地内存还是“静态”(自动)本地内存,例如local float[64]?
  • 也看看here
  • @Baizz 静态本地内存。我在发布之前看到了这个问题,但我看不出他们中的任何一个如何帮助弄清楚为什么工作组的规模是有限的。

标签: opencl mali


【解决方案1】:

还有哪些其他因素(例如,寄存器/__private 内存?)导致低 CL_KERNEL_WORK_GROUP_SIZE,如何检查使用情况?

在 Mali 上,计算工作负载使用的所有内存都是全局内存(即支持我的系统 RAM),因此内存压力不会导致任何问题,除非通过次要影响(例如缓存抖动)。我怀疑寄存器分配约束可能会在这里发挥作用——更大的工作组意味着着色器核心中活动的并发线程更多,这意味着对寄存器文件的压力更大——尽管我不确定。

用于 OpenGL ES 的 Mali 离线编译器报告工作寄存器的使用情况 - 例如,它可以报告此类信息:

./malisc -c Mali-T760 -r r1p0 -d Mali-T600_r5p0-00rel0 --fragment -V test.frag 
ARM Mali Offline Compiler v4.5.0
(C) Copyright 2007-2014 ARM Limited.
All rights reserved.


1 work registers used, 0 uniform registers used, spilling not used.

        A   L/S T   Total   Bound
Cycles:     2   0   0   2   A
Shortest Path:  1   0   0   1   A
Longest Path:   1   0   0   1   A

Note: The cycles counts do not include possible stalls due to cache misses.

我不确定 ARM 是否有可以报告类似信息的 OpenCL 离线编译器 - 可能值得在 ARM Connected Community 网站上询问。

【讨论】:

    【解决方案2】:

    编辑

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

    通过说“某些内核报告 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 可能还有更多,但目前没有想到。

    一般信息:

    可以限制工作组的大小,因为本地内存是有限的。如果你有一个使用大量私有内存的内核,则可以达到这个限制(“lots”是一个相对术语——在较弱的硬件上,即使看起来很少有变量也可能达到这个限制)。 “但是这个限制只是在理想条件下。如果您的内核在每个 WG 中使用大量 WI,则可能某些私有 WI 数据会溢出到本地内存中。[...]”(Source)。

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

    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 个。

    【讨论】:

    • 等等,你是说CL_DEVICE_LOCAL_MEM_SIZE是本地内存剩余的数量吗?我认为这是使用的本地内存量。如果它的使用量如我所想,
    • 阅读文档后发现我错了。 CL_DEVICE_LOCAL_MEM_SIZE 返回本地内存的可用大小,CL_KERNEL_LOCAL_MEM_SIZE 告诉您使用了多少本地内存。显然,这也通过查看clSetKernelArg 考虑了动态本地内存,但是我不确定如果您在设置内核参数之前查询CL_KERNEL_LOCAL_MEM_SIZE 这应该如何工作(这是您想要做的以确定本地内存的大小...)。无论如何,我可能不得不重新考虑你的问题和我的答案。
    • you're implying that kernels exist where a larger work-group size is available. Is that the case? 是的,在许多内核上,即使在 Mali 上,支持的工作组大小也是 128 或 256。我将在本周末或下周初您提到的所有参数,并报告回来。感谢您顺便帮忙!
    • 你有什么消息吗?
    猜你喜欢
    • 1970-01-01
    • 2017-01-01
    • 1970-01-01
    • 2020-10-25
    • 2011-03-15
    • 2018-10-23
    • 1970-01-01
    • 2012-07-13
    • 2015-01-04
    相关资源
    最近更新 更多