CUDA注册用法

use*_*436 3 cuda gpu

CUDA手册指定每个多处理器的32位寄存器的数量.这是否意味着:

  1. 双变量需要两个寄存器?

  2. 指针变量需要两个寄存器? - 它必须是Fermi上不止一个具有6 GB内存的寄存器,对吧?

  3. 如果对问题2的回答是肯定的,那么使用较少的指针变量和更多的int索引一定更好.

    例如,这个内核代码:

    float* p1;               // two regs
    float* p2 = p1 + 1000;   // two regs
    int i;                   // one reg
    for ( i = 0; i < n; i++ )
    {
        CODE THAT USES p1[i] and p2[i]
    }
    
    Run Code Online (Sandbox Code Playgroud)

    理论上需要比这个内核代码更多的寄存器:

    float* p1;               // two regs
    int i;                   // one reg
    int j;                   // one reg
    for ( i = 0, j = 1000; i < n; i++, j++ )
    {
        CODE THAT USES p1[i] and p1[j]
    }
    
    Run Code Online (Sandbox Code Playgroud)

tal*_*ies 8

对你的三个问题的简短回答是:

  1. 是.
  2. 是的,如果代码是为64位主机操作系统编译的.设备指针大小始终与CUDA中的主机应用程序指针大小匹配.
  3. 没有.

要扩展第3点,请考虑以下两个简单的内存复制内核:

__global__
void debunk(float *in, float *out, int n)
{
    int i = n * (threadIdx.x + blockIdx.x*blockDim.x);

    for(int j=0; j<n; j++) {
        out[i+j] = in[i+j];
    }
}

__global__
void debunk2(float *in, float *out, int n)
{
    int i = n * (threadIdx.x + blockIdx.x*blockDim.x);
    float *x = in + i;
    float *y = out + i;

    for(int j=0; j<n; j++, x++, y++) {
        *x = *y;
    }
}
Run Code Online (Sandbox Code Playgroud)

通过计算,debunk 必须使用较少的寄存器,因为它只有两个局部整数变量,而debunk2有两个额外的指针.然而,当我使用CUDA 5发布工具链编译它们时:

$ nvcc -m64 -arch=sm_20 -c -Xptxas="-v"  pointer_size.cu 
ptxas info    : 0 bytes gmem
ptxas info    : Compiling entry function '_Z6debunkPfS_i' for 'sm_20'
ptxas info    : Function properties for _Z6debunkPfS_i
    0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info    : Used 8 registers, 52 bytes cmem[0]
ptxas info    : Compiling entry function '_Z7debunk2PfS_i' for 'sm_20'
ptxas info    : Function properties for _Z7debunk2PfS_i
    0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info    : Used 8 registers, 52 bytes cmem[0]
Run Code Online (Sandbox Code Playgroud)

它们编译为完全相同的寄存器计数.如果您反汇编工具链输出,您将看到除了设置代码之外,最终的指令流几乎相同.这有很多原因,但它基本上归结为两个简单的规则:

  1. 试图从C代码(甚至是PTX汇编程序)确定寄存器计数大多是徒劳的
  2. 试图再次猜测一个非常复杂的编译器和汇编程序也是徒劳的.