首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >我能否确保NVCC已设法将数组放入寄存器?

我能否确保NVCC已设法将数组放入寄存器?
EN

Stack Overflow用户
提问于 2018-06-04 00:27:34
回答 1查看 192关注 0票数 0

带有一些本地的固定大小数组的CUDA内核可能会被编译,使得数组驻留在线程的“本地内存”中,或者-如果NVCC可以在编译时确定每个数组访问的位置,并且有足够的寄存器可用-该数组可能会被分解,其元素驻留在寄存器中。

是否可以通过代码或作为构建过程的一部分,检查或确保特定的数组或内核中的所有局部数组都已装入寄存器?有没有工具支持这样做?

EN

回答 1

Stack Overflow用户

发布于 2018-06-04 03:31:53

运行时的

使用CUDA driver API函数cuFuncGetAttribute,您可以使用CU_FUNC_ATTRIBUTE_LOCAL_SIZE_BYTES来提示您的阵列是否已注册。但对于某些用例,运行时可能太晚了。

编译时的

您需要查看生成的ptx文件(在nvcc中使用--keep选项)。

本地数据删除在ptx中被标识为.local。下面是一个带有内核的小示例。

代码语言:javascript
复制
#define ww 65

__global__ void kernel(int W, int H, const int *a, int *b)
{
    int buffer[ww];

    for (int i = threadIdx.x; i < H; i += blockDim.x)
    {
        #pragma unroll
        for (int w = 0; w < ww; ++w)
            buffer[w] = a[i + w * W];

        for (int j = 5; j < H - 5; ++j)
        {
            buffer[j % ww] = a[i + (j + 6) * W];

            int s = 0;
            #pragma unroll 
            for (int w = 0; w < ww; ++w)
                s += buffer[w];

            b[i + (j + 6) * W] = s;
        }
    }
}

编译时,有一个局部变量的声明:

代码语言:javascript
复制
.visible .entry _Z6kerneliiPKiPi(
    .param .u32 _Z6kerneliiPKiPi_param_0,
    .param .u32 _Z6kerneliiPKiPi_param_1,
    .param .u64 _Z6kerneliiPKiPi_param_2,
    .param .u64 _Z6kerneliiPKiPi_param_3
)
{
    .local .align 4 .b8     __local_depot0[260];
    .reg .b64   %SP;
    .reg .b64   %SPL;
    .reg .pred  %p<5>;
    .reg .b32   %r<219>;
    .reg .b64   %rd<81>;

但是,在滚动缓冲区时,总是使用已知的索引访问buffer,并且可以获得寄存器-没有本地存储:

代码语言:javascript
复制
#define ww 65

__global__ void kernel(int W, int H, const int *a, int *b)
{
    int buffer[ww];

    for (int i = threadIdx.x; i < H; i += blockDim.x)
    {
        #pragma unroll
        for (int w = 0; w < ww; ++w)
            buffer[w] = a[i + w * W];

        for (int j = 5; j < H - 5; ++j)
        {
            #pragma unroll 
            for (int w = 0; w < ww-1; ++w)
                buffer[w] = buffer[w + 1];
            buffer[ww - 1] = a[i + (j + 6) * W];

            int s = 0;
            #pragma unroll 
            for (int w = 0; w < ww; ++w)
                s += buffer[w];

            b[i + (j + 6) * W] = s;
        }
    }
}

生成以下ptx:

代码语言:javascript
复制
.visible .entry _Z6kerneliiPKiPi(
    .param .u32 _Z6kerneliiPKiPi_param_0,
    .param .u32 _Z6kerneliiPKiPi_param_1,
    .param .u64 _Z6kerneliiPKiPi_param_2,
    .param .u64 _Z6kerneliiPKiPi_param_3
)
{
    .reg .pred  %p<5>;
    .reg .b32   %r<393>;
    .reg .b64   %rd<240>;

请注意,根据可用寄存器的数量,所需寄存器的数量可能不适合。这些是虚拟寄存器(在最近的CUDA版本中以某种方式发生了变化)。这意味着没有.local .align 4 .b8 __local_depot是一个先决条件,但不是充分条件。

那你就需要看一下SASS了。在生成的.cubin上使用nvdisasm,您希望搜索STL指令,它代表STore本地,正如here简要描述的那样。以下是使用两个不同的--maxrregcount编译器开关值编译的两个反汇编立方体的一部分-首先是32 (请参阅多次出现的STL):

代码语言:javascript
复制
//--------------------- .text._Z6kerneliiPKiPi    --------------------------
    .section    .text._Z6kerneliiPKiPi,"ax",@progbits
    .sectioninfo    @"SHI_REGISTERS=32"
    .align  32
        .global         _Z6kerneliiPKiPi
        .type           _Z6kerneliiPKiPi,@function
        .size           _Z6kerneliiPKiPi,(.L_25 - _Z6kerneliiPKiPi)
        .other          _Z6kerneliiPKiPi,@"STO_CUDA_ENTRY STV_DEFAULT"
_Z6kerneliiPKiPi:
.text._Z6kerneliiPKiPi:
        /*0008*/                   MOV R1, c[0x0][0x20];
        /*0010*/         {         IADD32I R1, R1, -0x180;
        /*0018*/                   S2R R0, SR_TID.X;        }
        /*0028*/                   ISETP.GE.AND P0, PT, R0, c[0x0][0x144], PT;
        /*0030*/                   NOP;
        /*0038*/                   NOP;
        /*0048*/               @P0 EXIT;
.L_3:
        /*0050*/                   IADD R2, R0, c[0x0][0x140];
        /*0058*/                   MOV R30, c[0x0][0x140];
        /*0068*/                   ISCADD R5.CC, R2.reuse, c[0x0][0x148], 0x2;
        /*0070*/         {         SHR R3, R2, 0x1e;
        /*0078*/                   STL [R1+0x14], R5;        }
        /*0088*/                   ISCADD R2, R30.reuse, R0.reuse, 0x1;
        /*0090*/                   ISCADD R4, R30.reuse, R0.reuse, 0x2;
        /*0098*/                   ISCADD R20, R30, R0, 0x3;
        /*00a8*/                   IADD.X R5, R3, c[0x0][0x14c];
        /*00b0*/         {         SHR R3, R2.reuse, 0x1e;
        /*00b8*/                   STL [R1+0x10], R5;        }
        /*00c8*/                   ISCADD R2.CC, R2, c[0x0][0x148], 0x2;
        /*00d0*/                   STL [R1+0x8], R2;
        /*00d8*/                   SHR R5, R4, 0x1e;
        /*00e8*/                   IADD.X R2, R3, c[0x0][0x14c];
        /*00f0*/         {         ISCADD R4.CC, R4, c[0x0][0x148], 0x2;
        /*00f8*/                   STL [R1+0x4], R2;        }

那么对于255 -没有出现STL

代码语言:javascript
复制
//--------------------- .text._Z6kerneliiPKiPi    --------------------------
    .section    .text._Z6kerneliiPKiPi,"ax",@progbits
    .sectioninfo    @"SHI_REGISTERS=124"
    .align  32
        .global         _Z6kerneliiPKiPi
        .type           _Z6kerneliiPKiPi,@function
        .size           _Z6kerneliiPKiPi,(.L_25 - _Z6kerneliiPKiPi)
        .other          _Z6kerneliiPKiPi,@"STO_CUDA_ENTRY STV_DEFAULT"
_Z6kerneliiPKiPi:
.text._Z6kerneliiPKiPi:
        /*0008*/                   MOV R1, c[0x0][0x20];
        /*0010*/                   S2R R0, SR_TID.X;
        /*0018*/                   ISETP.GE.AND P0, PT, R0, c[0x0][0x144], PT;
        /*0028*/                   NOP;
        /*0030*/                   NOP;
        /*0038*/               @P0 EXIT;
        /*0048*/                   MOV R46, c[0x0][0x144];
        /*0050*/                   IADD R47, RZ, -c[0x0][0x140];
        /*0058*/                   IADD32I R46, R46, -0x5;
        /*0068*/                   SHL R47, R47, 0x2;
.L_3:
        /*0070*/                   ISETP.LT.AND P0, PT, R46, 0x6, PT;
        /*0078*/               @P0 BRA `(.L_1);
        /*0088*/                   MOV R2, c[0x0][0x140];
        /*0090*/                   ISCADD R2, R2, R0, 0x6;
        /*0098*/                   SHR R27, R2.reuse, 0x1e;
        /*00a8*/                   ISCADD R26.CC, R2, c[0x0][0x148], 0x2;
        /*00b0*/                   SHR R48, R47, 0x1f;
        /*00b8*/                   IADD.X R27, R27, c[0x0][0x14c];
        /*00c8*/         {         IADD R44.CC, R47.reuse, R26;
        /*00d0*/                   LDG.E R49, [R26];        }
        /*00d8*/                   IADD.X R45, R48.reuse, R27;
        /*00e8*/         {         IADD R42.CC, R47.reuse, R44  SLOT 0;
        /*00f0*/                   LDG.E R44, [R44]  SLOT 1;        }
        /*00f8*/                   IADD.X R43, R48.reuse, R45;
        /*0108*/         {         IADD R38.CC, R47, R42  SLOT 0;
        /*0110*/                   LDG.E R42, [R42]  SLOT 1;        }

我想我和你很像,我希望所有这些都被更好地记录下来。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50668536

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档