Cuda NVIDIA GPU部件代码(SASS)中的螺纹ID旋转

Cuda NVIDIA GPU部件代码(SASS)中的螺纹ID旋转,cuda,nvidia,Cuda,Nvidia,仔细查看NVIDIA sm_20 Architecture的SASS输出时,发现ThreadID是从特殊寄存器加载的,旋转分两步执行 使用通过旋转获得的值加载MSB寄存器 ThreadID由2留下 用获得的值加载LSB寄存器 通过将ThreadID向右旋转30 这将一起进行32位旋转,寄存器对将如下所示: 此外,只要代码中使用threadID,SASS中就会使用该寄存器对。SASS代码是 code for sm_20 Function : _Z3addPiS_S

仔细查看NVIDIA sm_20 Architecture的SASS输出时,发现ThreadID是从特殊寄存器加载的,旋转分两步执行

  • 使用通过旋转获得的值加载MSB寄存器 ThreadID由2留下
  • 用获得的值加载LSB寄存器 通过将ThreadID向右旋转30
  • 这将一起进行32位旋转,寄存器对将如下所示:

    此外,只要代码中使用threadID,SASS中就会使用该寄存器对。SASS代码是

        code for sm_20
                Function : _Z3addPiS_S_
        .headerflags    @"EF_CUDA_SM20 EF_CUDA_PTX_SM(EF_CUDA_SM20)"
        /*0000*/         MOV R1, c[0x1][0x100];         /* 0x2800440400005de4 */
        /*0008*/         S2R R2, SR_TID.X;              /* 0x2c00000084009c04 */---Getting thread ID
        /*0010*/         IMAD.U32.U32 RZ, R1, RZ, RZ;   /* 0x207e0000fc1fdc03 */
        /*0018*/         SHL.W R3, R2, 0x2;             /* 0x6000c0000820de03 */---Rotating Step 1
        /*0020*/         SHR.U32 R4, R2, 0x1e;          /* 0x5800c00078211c03 */---Rotating Step 2
        /*0028*/         IADD R6.CC, R3, c[0x0][0x20];  /* 0x4801400080319c03 */
        /*0030*/         IADD.X R7, R4, c[0x0][0x24];   /* 0x480040009041dc43 */
        /*0038*/         LD.E R0, [R6];                 /* 0x8400000000601c85 */
        /*0040*/         STS [R3], R0;                  /* 0xc900000000301c85 */---Shared mem access with ThreadID
    
    这样做的目的是什么,而不是使用从特殊寄存器加载的ThreadID?

    sm_20的代码 功能:_

    Demangled=add(int*,int*,int*)


    整个内核函数在做什么?也许你可以从更高的层次上得到线索。人们通常在给定
    threadIdx.x
    的情况下计算出某个值,然后将其用作访问共享/全局内存的偏移量。我可以理解乘以4的逻辑。这是因为int的大小是4。但是当我们把R3-R4看作登记对时,当2个MSB位放在R4时它会如何帮助。我必须看到源代码。我怀疑编译器正在将threadIdx.x(uint32_t)升级为uint64_t,这将要求threadIdx.x的2 MSB下移到高32位的2 LSB。编译器不知道threadIdx.x的范围有限,因为内置的数据类型是uint3。
    MOV R1, c[0x1][0x100];      
    S2R R2, SR_TID.X;               // read threadIdx.x
    IMAD.U32.U32 RZ, R1, RZ, RZ;
    SHL.W R3, R2, 0x2;              // r3 = threadIdx.x * 4 (int* pointer math)
    SHR.U32 R4, R2, 0x1e;           // r4 = threadIdx.x[31:30] to make 64-bit offset in R3/R4
    IADD R6.CC, R3, c[0x0][0x20];   // add a constant (parameter 0 - lower 32-bits)
    IADD.X R7, R4, c[0x0][0x24];    // add a constant (parameter 0 - upper 32-bits)
    LD.E R0, [R6];                  // load the 32-bit value from address R6/R7 into R0
    STS [R3], R0;                   // store the 32-bit value in R0 into shared offset threadIdx.x * 4