OpenCl寄存器的神奇数字

7

我编写了两个不同的 OpenCl 内核,使用 NVIDIA 分析工具获取了一些信息,并发现两者都使用了每个工作项 63 个寄存器。

我尝试了我所能想到的一切来降低这个数字(用 ushort 替换 int,在 {} 中声明变量以告诉编译器何时可以摆脱它们),但似乎不可能改变这个 63!

然后我找到了一个关于他编写的内核的另一个问题,它也使用了 63 个寄存器。

当然,这可能是纯粹巧合,但也可能有原因......可能是使用了特定的函数、硬件限制?有人知道吗?


你认为为什么使用ushort而不是int会减少寄存器的使用数量? - Grizzly
因为寄存器用于存储频繁使用的变量,从而避免访问全局/本地内存的成本。因此,如果您存储float和ushort而不是double和int,则可以节省一些空间。我尝试了一个简单的内核,并有效地发现使用新的double变量使用了两个寄存器,这是有道理的,因为一个寄存器是32位,而double是64位。 - Istopopoki
从64位到32位时,您可以保存寄存器,这是真的。但是,由于寄存器本来就是32位的,因此使用ushort几乎不可能使您获得任何优势。关于变量的缓存:我不确定避免显式访问本地/全局内存是否合法,因为其他工作项可能会修改内存。对于内核中的局部变量:它们通常都驻留在寄存器中(至少在硬件限制之前)。将它们存储在全局内存中将非常缓慢,而本地内存太小了(实际上比寄存器空间还小)。 - Grizzly
当我在官方文档中读到“具有计算能力1.0和1.1的设备每个多处理器有8,192个32位寄存器”时,我不知道它是否意味着我可以使用8,192 * 32位寄存器,这意味着两个16位的无符号短整型(每个短整型为16位)可以适合一个32位寄存器,或者无论其大小如何,我都不能在寄存器中存储超过8,192个变量。在这种情况下,对于我的目的,使用ushort将是无效的。但我仍然想知道“63”是否对应某些内容。 - Istopopoki
理论上,编译器可以选择将两个变量存储在一个寄存器中,但这种情况不太可能发生,因为它会使生成的代码更加复杂(需要从寄存器中提取变量才能使用...),这意味着速度会变慢。不过,我无法帮你解决63的问题。 - Grizzly
以前从未遇到过这样的问题,但也许编译器认为使用64个寄存器没有任何危害(例如占用等)。 - alariq
2个回答

5

大多数最新硬件(例如GTX 480到GTX 770)最多可以使用63个寄存器。只有使用GTX 780或Tesla K20才能获得每个线程255个寄存器。

因此,当您的内核使用63个寄存器时,它很可能使用的寄存器数量超过了63个,但这些寄存器将被溢出到离线芯片私有内存(也称为CUDA本地内存)。例如,如果您的Nvidia分析器报告了128字节的本地内存,则表示您需要在降至63个硬件寄存器之前摆脱32个(溢出的)寄存器。

顺便说一句,“每个多处理器的8192个32位寄存器”意味着所有驻留在多处理器上的工作组都有8192个寄存器。但通常,工作组的数量受到工作组大小和内核所需寄存器数量的限制。例如,如果您的内核使用63个寄存器,并且您的工作组大小为16^2,则您会得到:63 * 16 ^ 2 = 16128个寄存器每个工作组。假设您每个多处理器有64K个寄存器,则每个多处理器可以有4个工作组驻留,这将产生25%的占用率。


0

每个线程的最大寄存器数量受硬件限制,取决于设备的“计算能力”。请查看表格计算能力

(这适用于NVidia,其他供应商可能有其他限制)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接