强制CUDA对变量使用寄存器

强制CUDA对变量使用寄存器,cuda,Cuda,我的内核中有许多未使用的寄存器。我想告诉CUDA使用一些寄存器来保存一些数据,而不是在每次需要时进行全局数据读取。(我无法使用共享内存。) 知道在哪里可以找到真正的机器/编译代码吗? 动态索引数组不能存储在寄存器中,因为GPU寄存器文件不可动态寻址 标量变量由编译器自动存储在寄存器中 静态索引(即,可在编译时确定索引的位置),编译器可将小数组(例如,小于16个浮点)存储在寄存器中 SM 2.0 GPU(费米)仅支持每个线程最多63个寄存器。如果超过此值,则寄存器值将从缓存层次结构支持的本地(片

我的内核中有许多未使用的寄存器。我想告诉CUDA使用一些寄存器来保存一些数据,而不是在每次需要时进行全局数据读取。(我无法使用共享内存。)

知道在哪里可以找到真正的机器/编译代码吗?

  • 动态索引数组不能存储在寄存器中,因为GPU寄存器文件不可动态寻址
  • 标量变量由编译器自动存储在寄存器中
  • 静态索引(即,可在编译时确定索引的位置),编译器可将小数组(例如,小于16个浮点)存储在寄存器中
SM 2.0 GPU(费米)仅支持每个线程最多63个寄存器。如果超过此值,则寄存器值将从缓存层次结构支持的本地(片外)内存溢出/填充。SM 3.5 GPU将此扩展到每个线程最多255个寄存器

一般来说,正如Jared所提到的,每个线程使用太多寄存器是不可取的,因为这样可以减少占用,从而降低内核中的延迟隐藏能力。GPU依赖并行性,通过使用其他线程的工作来覆盖内存延迟

因此,您可能不应该将数组优化为寄存器。相反,请确保跨线程对这些阵列的内存访问尽可能按顺序进行,以便最大化合并(即最小化内存事务)

您给出的示例可能是共享内存的情况,如果:

  • 块中的多个线程使用相同的数据,或
  • 每个线程的数组大小足够小,可以为多个线程块中的所有线程分配足够的空间(每个线程1024个浮点远远不够)

  • 正如njuffa所提到的,内核只使用2个寄存器的原因是,您没有对内核中的数据做任何有用的操作,并且死代码都被编译器清除。

    如前所述,寄存器(以及PTX“param space”)无法动态索引。为了做到这一点,编译器必须为
    switch…case
    块发出代码,以将动态索引转换为立即索引。我不确定它是否会自动运行。您可以使用一个固定大小的元组结构和一个
    开关…case
    来帮助实现这一点。C/C++元编程很可能是使这样的代码易于管理的首选武器

    此外,对于CUDA 4.0,使用命令行开关
    -Xopencc=-O3
    ,以便将普通标量(如数据结构)以外的任何东西映射到寄存器(请参阅)。对于CUDA>4.0,必须禁用调试支持(无
    -G
    命令行选项-只有禁用调试时才会进行优化)

    PTX级别允许比硬件更多的虚拟寄存器。这些在加载时映射到硬件寄存器。指定的寄存器限制允许您对生成的二进制文件使用的硬件资源设置上限。当编译到PTX时,它可以作为一种启发式方法,让编译器决定何时溢出(请参见下文)寄存器,以便满足某些并发需求(请参见CUDA文档中的“启动边界”、“占用”和“并发内核执行”——您可能也会喜欢)


    对于费米GPU,最多有64个硬件寄存器。ABI将第64个(或最后一个-当使用少于硬件最大值时)用作堆栈指针,因此用于“寄存器溢出”(这意味着通过临时将寄存器的值存储在堆栈上释放寄存器,并在需要的寄存器比可用寄存器多时发生),因此它是不可触及的。

    编译器优化了整个代码,因为它不修改任何非瞬态状态。要求每个线程有1024个寄存器是一个相当高的要求。大多数内核每个线程需要几十个寄存器。如果您想绝对确保编译器可以为变量使用寄存器,那么它必须是标量(即,不是在
    循环中为
    编制索引的数组)。可以在此处找到where/what堆栈帧答案:float a1、a2、a3、a4、a5;//每个“a”都有一个reg。挥发性浮子b1、b2、b3、b4、b5;//每个“b”都在堆栈上(本地内存)。“volatile”声明对reg分配没有任何作用,但它确实创建了一个本地mem堆栈。您的意思是,线程可以使用的#of reg有一个限制(对于SM#u 20,63)。这是从哪里来的?设备属性显示对每个块(regsPerbBock)的#个寄存器的限制。它来自于体系结构,编译器负责确保生成的二进制代码中没有使用大于限制的寄存器号。除了性能原因(例如,为了理解寄存器溢出的原因),用户不必担心这个限制,这就是为什么不需要在deviceProps结构中列出它的原因。可能需要使用许多寄存器,因为最大化占用率并不是隐藏延迟的唯一方法。另一种隐藏延迟的方法是指令级并行。有时,这是达到最高性能的唯一途径。查看Vasily Volkov,autor在8%的占用率下获得了最高性能。关于-Xopencc=-O3的链接消失了,我在CUDA的上下文中找不到任何与此相关的参考。你能给我指出一些资源或解释一下最近cuda(7.0/7.5)的行为是否类似吗?
    
    __global__ void simple(float *gData) {
    float rData[1024];
    for(int i=0; i<1024; i++) {
      rData[i]=gData[i];
      }
    // work on the data here
    }
    
    __global__ void simple(float *gData) {
    register float rData[1024];
    for(int i=0; i<1024; i++) {
      rData[i]=gData[i];
      }
    // work on the data here
    }
    
    __global__ void simple(float *gData) {
    volatile float rData[1024];
    for(int i=0; i<1024; i++) {
      rData[i]=gData[i];
      }
    // work on the data here
    }
    
    .loc 2 14 2
    ret;