OpenCl 寄存器的幻数
Posted
技术标签:
【中文标题】OpenCl 寄存器的幻数【英文标题】:The magic number of OpenCl registers 【发布时间】:2012-11-28 03:42:21 【问题描述】:我编写了两个不同的 openCl 内核,使用 nvidia 分析器获取了一些关于它们的信息,发现它们每个工作项都使用 63 个寄存器。
我尝试了我能想到的一切来降低这个数字(用 ushort 替换 int,尝试在 中声明变量以显示编译器何时可以摆脱它们)但似乎不可能改变这个 63!
然后我发现another question 是关于他编写的一个内核,该内核使用...再次使用 63 个寄存器。
当然这可能纯属巧合,但也许背后有某种原因……使用的特定功能,硬件限制?有人知道吗?
【问题讨论】:
为什么你认为使用ushort
而不是int
会减少使用的寄存器数量?
因为寄存器用于存储经常使用的变量,从而避免昂贵的访问全局/局部内存。因此,如果您存储 float 和 ushort 而不是 double 和 int,则可以节省一些空间。我尝试了一个简单的内核,并有效地看到使用新的双精度变量使用了两个寄存器,这是有意义的,因为寄存器是 32 位,双精度是 64。
从 64 位到 32 位时,您可以节省寄存器,这是真的。但是,由于寄存器无论如何都是 32 位的,因此使用 ushort` 不太可能为您赢得任何东西。关于变量的缓存:我不确定避免显式访问本地/全局内存是否合法,因为其他工作项可能会修改内存。对于内核中的局部变量:这些通常都应该驻留在寄存器中(至少在您达到硬件限制之前)。将它们存储在全局内存中会非常慢,并且本地内存是有限的(反正不会比寄存器空间大)。
当我在官方文档中阅读“具有计算能力 1.0 和 1.1 的设备每个多处理器有 8,192 个 32 位寄存器”时,我不知道这是否意味着我可以使用 8,192*32 位寄存器,这意味着两个 ushorts(每个 16 位)可以放在一个 32 位寄存器中,或者如果我不能在寄存器中存储超过 8,192 个变量,无论它们的大小。在那种情况下,使用 ushort 对于我的目的实际上是无用的。但我仍然想知道“63”是否对应于某物。
理论上编译器可以选择两个在一个寄存器中存储两个变量,但是不太可能这样做,因为它使生成的代码更加复杂(使用需要提取的变量从寄存器中,...),意思是更慢。不过 63 不能帮你。
【参考方案1】:
最多 63 个寄存器。在大多数最新硬件(如 GTX 480 到 GTX 770)上的数量。只有使用 GTX 780 或 Tesla K20,每个线程才能获得 255 个寄存器。
因此,当您的内核使用 63 个寄存器时,很可能会使用超过 63 个的寄存器,但它们会溢出到片外私有内存(也称为 CUDA 本地内存)。例如,如果您的 nvidia 分析器报告 128 字节的本地内存,则意味着您需要摆脱 32 个(溢出)寄存器,然后才能获得低于 63 个硬件寄存器。
顺便说一句:“每个多处理器 8,192 个 32 位寄存器”意味着驻留在多处理器上的所有工作组有 8,192 个寄存器。但通常工作组的数量受工作组大小和内核需要的寄存器数量的限制。例如,如果您的内核使用 63 个寄存器并且您的工作组大小为 16^2,您将得到:63*16^2 = 每个工作组 16128 个寄存器。假设每个多处理器有 64K 寄存器,那么每个多处理器上可以驻留 4 个工作组,这将产生 25% 的占用率。
【讨论】:
【参考方案2】:最大。寄存器/线程的数量受硬件限制,并且取决于设备的“计算能力”。看看表 Compute Capabilities。
(这适用于 NVidia,其他供应商可能有其他限制)。
【讨论】:
以上是关于OpenCl 寄存器的幻数的主要内容,如果未能解决你的问题,请参考以下文章