Memory 提高CUDA中每线程寄存器的使用率

Memory 提高CUDA中每线程寄存器的使用率,memory,cuda,latency,cpu-registers,Memory,Cuda,Latency,Cpu Registers,通常建议降低每线程寄存器压力以增加扭曲占用率,从而通过扭曲级别多线程(TLP)提供更大的隐藏延迟的机会。要降低寄存器压力,可以使用更多的每个线程本地内存或每个线程块共享内存。CUDA nvcc编译器也可以强制每个线程使用更少的寄存器。这种方法适用于具有良好算术延迟的工作负载,即ALU操作与内存r/w访问请求的比率较高。但是,对于计算量很少且内存访问更频繁的延迟关键型应用程序,这种方法实际上会降低性能 对于这种延迟关键型应用程序,将尽可能多的数据放入片上寄存器或共享内存中,然后在使用全局内存中的下

通常建议降低每线程寄存器压力以增加扭曲占用率,从而通过扭曲级别多线程(TLP)提供更大的隐藏延迟的机会。要降低寄存器压力,可以使用更多的每个线程本地内存或每个线程块共享内存。CUDA nvcc编译器也可以强制每个线程使用更少的寄存器。这种方法适用于具有良好算术延迟的工作负载,即ALU操作与内存r/w访问请求的比率较高。但是,对于计算量很少且内存访问更频繁的延迟关键型应用程序,这种方法实际上会降低性能

对于这种延迟关键型应用程序,将尽可能多的数据放入片上寄存器或共享内存中,然后在使用全局内存中的下一块数据替换之前尽可能多地使用这些数据更有意义。当然,通过增加寄存器压力,翘曲占用率降低,但现在我们使用快速片上寄存器来隐藏片外内存延迟。增加每个线程寄存器使用率的方法是通过展开循环或计算每个线程的更多输出数据来增加ILP(这也基本上通过对更多输入执行相同的工作来增加ILP)。这种方法基本上是由Volkov提出的(在占用率较低的情况下性能更好)


现在nvcc编译器驱动程序有一个名为maxrregcount的命令行选项,它允许更改每线程寄存器的使用情况。使用此选项一次可以强制编译器减少每线程寄存器的使用,但不能强制编译器增加每线程寄存器的使用。我有一个例子,我想增加每线程寄存器的使用率,但我无法在内核中展开循环,因为循环边界依赖于数据并且是动态的。到目前为止,我尝试了一些技巧,但对于如何提高每线程寄存器的使用率,我已经没有什么想法了。有人能提出提高单个CUDA线程的寄存器使用率的方法吗?

在某种程度上,这个问题是重复的。您已经很好地总结了这些选项。如果您不能通过展开和显式使用标量变量强制使用寄存器,那么我认为您可能会陷入困境

请注意,即使是具有动态边界的循环也可以部分手动展开。您只需检查循环展开部分内的边界。这可能有助于提高寄存器的使用率

我还认为,增加寄存器使用率和减少延迟之间并没有保证的直接关系,所以实际上您应该关注减少延迟,而不是特别关注寄存器使用率

如果您想减少总体内核延迟,那么您应该尝试一些方法

  • 启动的线程块不能超过GPU上可并发运行的线程块(由占用率计算器确定)
  • 尽量减少内核的函数参数数量,因为这些参数需要在内核启动期间初始化(因此,拥有许多参数会增加启动开销)

    • 这个问题的结构就像是在问:“我怎样才能在商店里为牛奶支付更多的钱?”这个问题是颠倒的。你应该问的是,“我有一定数量的钱,我如何用它来获得尽可能多的牛奶?”

      好的,这不是最好的类比,但基本上,问题是,增加寄存器计数本身就是目标,当然,目标是提高性能

      所以,首先要确定的是,你是否有你认为的那么多寄存器?如果寄存器是内核中的占用限制因素。当内核内存受限时,更改代码以使用更多寄存器可能不是一个好主意

      如果您已经确定占用率受到其他因素的限制,那么您可以询问是否可以通过使用更多寄存器来提高性能(在寄存器成为占用限制因素之前,寄存器是“空闲的”)


      为了达到这个目的,您可以开始考虑一些选项。

      有趣的问题!我也在尝试使用ILP的这种方法来提供更好的性能!事实上,由于我受到较旧的GPU体系结构的限制,每个线程分配的寄存器较少,因此使用ILP实际上提高了性能,因为它通过循环展开(独立指令)释放寄存器以进行更多的计算工作

      我想知道你们有多少嵌套循环?如果内部循环无法展开,可能会上升一个级别并寻找机会

      为了增加每个线程的寄存器使用率,是否减少了启动的块数(线程数较少)?
      要提高寄存器/线程的使用率,请加载多组并行执行的数据

      它在循环的每个迭代中都是独立的吗?我相信关键是寻找独立的计算。 分批执行如何。假设循环计数为N,将其拆分为N/M并独立计算


      当你提供一点线索时,很难给出建议:p

      对不起,但这个问题在我看来完全是荒谬的。@Roger Dahl:如果你读了我提到的那篇文章,你就会明白我在这里试图表达的观点。我认为你关于入住率的评论是错误的。努拉夫不需要减少占用率限制资源,因为增加占用率可能会产生他想要的完全相反的效果。它可能会增加延迟。他希望减少延迟,而不是增加吞吐量。增加占用率并不能减少延迟。在一定程度上(当有空闲插槽需要填充时),增加占用率不会增加延迟,但一旦SMs每个周期完成一条指令,进一步增加占用率只会增加延迟。@harrism:没错。增加内核占用率实际上会降低性能。增加占用率只能在一定程度上减少延迟Nurava和@harrism:感谢您提供的信息和反馈。我读了报纸,现在明白了