【问题标题】:Utilizing Register memory in CUDA在 CUDA 中使用寄存器内存
【发布时间】:2023-04-03 08:23:01
【问题描述】:

我有一些关于 cuda 寄存器内存的问题

1) 有没有办法释放 cuda 内核中的寄存器?我在寄存器中有变量、一维和二维数组。 (最大数组大小 48)

2)如果我使用device函数,那么我在device函数中使用的寄存器在执行后会发生什么?它们是否可用于调用内核执行或其他设备功能?

3) nvcc 如何优化寄存器使用?请分享内存密集型内核优化的重要要点

PS:我有一个复杂的算法可以移植到 cuda,它需要大量寄存器进行计算,我试图弄清楚是将中间数据存储在寄存器中并编写一个内核还是将其存储在全局内存中并中断算法在多个内核中。

【问题讨论】:

    标签: cuda


    【解决方案1】:

    只有局部变量才有资格驻留在寄存器中(另请参阅Declaring Variables in a CUDA kernel)。您无法直接控制哪些变量(标量或静态数组)将驻留在寄存器中。编译器将做出自己的选择,在寄存器备用方面争取性能。

    可以使用 nvcc 编译器的maxrregcount 选项限制寄存器的使用。

    您还可以将大多数小型 1D、2D 数组放在共享内存中,或者,如果访问常量数据,则将此内容放入常量内存(缓存非常接近作为 L1 缓存内容的寄存器)。

    在 CUDA 中处理计算绑定内核时减少寄存器使用的另一种方法是分阶段处理数据,使用多个全局内核函数调用并将中间结果存储到全局内存中。每个内核将使用更少的寄存器,因此每个 SM 的更多活动线程将能够隐藏加载/存储数据移动。这种技术与正确使用流和异步数据传输相结合,在大多数情况下都非常成功。

    关于设备函数的使用,我不确定,但我猜调用函数的寄存器内容将被移动/存储到本地内存(L1缓存左右),就像使用时发生寄存器溢出一样局部变量太多(请参阅CUDA Programming Guide -> Device Memory Accesses -> Local Memory)。此操作将为调用的设备函数释放一些寄存器。设备函数完成后,它们的局部变量不再存在,寄存器现在可以被调用函数再次使用并填充之前保存的内容。

    请记住,出于性能原因,在全局内核的同一源代码中定义的小型设备函数可能会被编译器内联:当这种情况发生时,生成的内核通常需要更多的寄存器。

    【讨论】:

    • 我已经在使用共享内存和常量内存,但由于算法的计算密集型特性,需要大量寄存器(>255,我实际上问了这个问题来计算所需的寄存器数量,而设计算法)。如果我将中间结果存储在全局内存中并将计算拆分到多个内核中,那么我确信我会在读写中浪费很多周期。让寄存器溢出到本地内存更好吗? (因此如果在下一代 GPU 中,如果每个线程的寄存器增加,将支持相同的算法)
    • @Adarsh:您不能仅从 CUDA 源代码中推断出使用的寄存器数量,这是一个编译器选择,您可以使用maxrregcount 或使用较少的局部变量进行限制。将代码从 CPU 移植到 CUDA 时,还要考虑将算法更改为更适合 GPU 硬件的算法。将你的大任务分成多个内核是计算绑定算法的最佳方法(答案更新):每个内核使用的寄存器越少,越活跃的线程将隐藏加载/存储。 nvvp 会告诉你你的内核是否属于这一类。不要“确定”,试试吧。
    • @Adarsh 如果我的回答让您满意,请签署已接受或澄清遗漏的内容。
    猜你喜欢
    • 1970-01-01
    • 2012-01-21
    • 1970-01-01
    • 2012-09-30
    • 1970-01-01
    • 1970-01-01
    • 2012-04-01
    • 2011-08-28
    • 1970-01-01
    相关资源
    最近更新 更多