反汇编CUDA微码中的明显冗余操作

反汇编CUDA微码中的明显冗余操作,cuda,disassembly,ptx,Cuda,Disassembly,Ptx,我让下面的内核执行一个简单的赋值,将全局内存矩阵in分配给全局内存矩阵out: __global__ void simple_copy(float *outdata, const float *indata){ int x = blockIdx.x * TILE_DIM + threadIdx.x; int y = blockIdx.y * TILE_DIM + threadIdx.y; int width = gridDim.x * TILE_DIM; o

我让下面的内核执行一个简单的赋值,将全局内存矩阵
in
分配给全局内存矩阵
out

__global__ void simple_copy(float *outdata, const float *indata){

    int x = blockIdx.x * TILE_DIM + threadIdx.x;
    int y = blockIdx.y * TILE_DIM + threadIdx.y;

    int width = gridDim.x * TILE_DIM;

    outdata[y*width + x] = indata[y*width + x];

}
我正在检查由
cuobjdump
转储的反汇编微码:

Function : _Z11simple_copyPfPKf
/*0000*/     /*0x00005de428004404*/     MOV R1, c [0x1] [0x100]; 
/*0008*/     /*0x80001de218000000*/     MOV32I R0, 0x20;            R0 = TILE_DIM
/*0010*/     /*0x00001c8614000000*/     LDC R0, c [0x0] [R0];       R0 = c
/*0018*/     /*0x90009de218000000*/     MOV32I R2, 0x24;            R2 = 36
/*0020*/     /*0x00209c8614000000*/     LDC R2, c [0x0] [R2];       R2 = c

int x = blockIdx.x * TILE_DIM + threadIdx.x;
/*0028*/     /*0x9400dc042c000000*/     S2R R3, SR_CTAid_X;         R3 = BlockIdx.x
/*0030*/     /*0x0c00dde428000000*/     MOV R3, R3;                 R3 = R3 ???
/*0038*/     /*0x84011c042c000000*/     S2R R4, SR_Tid_X;           R3 = ThreadIdx.x
/*0040*/     /*0x10011de428000000*/     MOV R4, R4;                 R4 = R4 ???
/*0048*/     /*0x8030dca32008c000*/     IMAD R3, R3, 0x20, R4;      R3 = R3 * TILE_DIM + R4  (contains x)

int y = blockIdx.y * TILE_DIM + threadIdx.y;
/*0050*/     /*0x98011c042c000000*/     S2R R4, SR_CTAid_Y;
/*0058*/     /*0x10011de428000000*/     MOV R4, R4;
/*0060*/     /*0x88015c042c000000*/     S2R R5, SR_Tid_Y;
/*0068*/     /*0x14015de428000000*/     MOV R5, R5;
/*0070*/     /*0x80411ca3200ac000*/     IMAD R4, R4, 0x20, R5;      R4 ...                   (contains y)

int width = gridDim.x * TILE_DIM;
/*0078*/     /*0x50015de428004000*/     MOV R5, c [0x0] [0x14];     R5 = c
/*0080*/     /*0x80515ca35000c000*/     IMUL R5, R5, 0x20;          R5 = R5 * TILE_DIM       (contains width)   

y*width + x
/*0088*/     /*0x14419ca320060000*/     IMAD R6, R4, R5, R3;        R6 = R4 * R5 + R3        (contains y*width+x)

Loads indata[y*width + x]
/*0090*/     /*0x08619c036000c000*/     SHL R6, R6, 0x2;            
/*0098*/     /*0x18209c0348000000*/     IADD R2, R2, R6;            
/*00a0*/     /*0x08009de428000000*/     MOV R2, R2;                 R2 = R2 ???
/*00a8*/     /*0x00209c8580000000*/     LD R2, [R2];                Load from memory - R2 = 

Stores outdata[y*width + x]
/*00b0*/     /*0x1440dca320060000*/     IMAD R3, R4, R5, R3;        
/*00b8*/     /*0x0830dc036000c000*/     SHL R3, R3, 0x2;
/*00c0*/     /*0x0c001c0348000000*/     IADD R0, R0, R3;            R0 = R0 + R3
/*00c8*/     /*0x00001de428000000*/     MOV R0, R0;                 R0 = R0 ???
/*00d0*/     /*0x00009c8590000000*/     ST [R0], R2;                Store to memory

/*00d8*/     /*0x40001de740000000*/     BRA 0xf0;
/*00e0*/     /*0x00001de780000000*/     EXIT;
/*00e8*/     /*0x00001de780000000*/     EXIT;
/*00f0*/     /*0x00001de780000000*/     EXIT;
/*00f8*/     /*0x00001de780000000*/     EXIT;
反汇编代码顶部或旁边的注释是我自己的

如您所见,注释中有一些显然无用的操作,标记为
。本质上,它们是寄存器自身的移动

我有以下两个问题:

  • 如果它们是无用的,我相信它们是在无用地消耗计算时间。我可以通过删除它们来优化反汇编的微码吗
  • PTX文件可以在CUDA代码中内联。然而,PTX只是跨GPU可移植性所需的中间语言。我能以某种方式“内联”一个优化的反汇编微码吗
  • 事先非常感谢

    编辑:在SM=2.0的发布模式下编译的相同代码

    Function : _Z11simple_copyPfPKf
    .headerflags    @"EF_CUDA_SM20 EF_CUDA_PTX_SM(EF_CUDA_SM20)"
    /*0000*/        MOV R1, c[0x1][0x100];            /* 0x2800440400005de4 */
    /*0008*/        S2R R0, SR_CTAID.Y;               /* 0x2c00000098001c04 */
    /*0010*/        S2R R2, SR_TID.Y;                 /* 0x2c00000088009c04 */
    /*0018*/        S2R R3, SR_CTAID.X;               /* 0x2c0000009400dc04 */
    /*0020*/        S2R R4, SR_TID.X;                 /* 0x2c00000084011c04 */
    /*0028*/        MOV R5, c[0x0][0x14];             /* 0x2800400050015de4 */
    /*0030*/        ISCADD R2, R0, R2, 0x5;           /* 0x4000000008009ca3 */
    /*0038*/        ISCADD R3, R3, R4, 0x5;           /* 0x400000001030dca3 */
    /*0040*/        SHL R0, R5, 0x5;                  /* 0x6000c00014501c03 */
    /*0048*/        IMAD R2, R0, R2, R3;              /* 0x2006000008009ca3 */
    /*0050*/        ISCADD R0, R2, c[0x0][0x24], 0x2; /* 0x4000400090201c43 */
    /*0058*/        ISCADD R2, R2, c[0x0][0x20], 0x2; /* 0x4000400080209c43 */
    /*0060*/        LD R0, [R0];                      /* 0x8000000000001c85 */
    /*0068*/        ST [R2], R0;                      /* 0x9000000000201c85 */
    /*0070*/        EXIT ;                            /* 0x8000000000001de7 */
    
    编辑:在SM=2.1的发布模式下编译的相同代码

    Function : _Z11simple_copyPfPKf
    .headerflags    @"EF_CUDA_SM20 EF_CUDA_PTX_SM(EF_CUDA_SM20)"
    /*0000*/        MOV R1, c[0x1][0x100];            /* 0x2800440400005de4 */
    /*0008*/        NOP;                              /* 0x4000000000001de4 */
    /*0010*/        MOV R0, c[0x0][0x14];             /* 0x2800400050001de4 */
    /*0018*/        S2R R2, SR_CTAID.Y;               /* 0x2c00000098009c04 */
    /*0020*/        SHL R0, R0, 0x5;                  /* 0x6000c00014001c03 */
    /*0028*/        S2R R3, SR_TID.Y;                 /* 0x2c0000008800dc04 */
    /*0030*/        ISCADD R3, R2, R3, 0x5;           /* 0x400000000c20dca3 */
    /*0038*/        S2R R4, SR_CTAID.X;               /* 0x2c00000094011c04 */
    /*0040*/        S2R R5, SR_TID.X;                 /* 0x2c00000084015c04 */
    /*0048*/        ISCADD R2, R4, R5, 0x5;           /* 0x4000000014409ca3 */
    /*0050*/        IMAD R2, R0, R3, R2;              /* 0x200400000c009ca3 */
    /*0058*/        ISCADD R0, R2, c[0x0][0x24], 0x2; /* 0x4000400090201c43 */
    /*0060*/        ISCADD R2, R2, c[0x0][0x20], 0x2; /* 0x4000400080209c43 */
    /*0068*/        LD R0, [R0];                      /* 0x8000000000001c85 */
    /*0070*/        ST [R2], R0;                      /* 0x9000000000201c85 */
    /*0078*/        EXIT ;                            /* 0x8000000000001de7 */
    

    这两个问题的答案都是否定的

    如果您试图从最终二进制有效负载中删除指令。您将更改代码段的长度并断开ELF和fatbinary文件。要解决这一问题,需要手工制作格式不易记录的头文件,这听起来需要做大量的工作来优化几个指令

    内联本机汇编程序不受支持,但我相信您已经知道了

    最后,我无法使用CUDA 5.0复制:

    Fatbin elf code:
    ================
    arch = sm_20
    code version = [1,6]
    producer = cuda
    host = mac
    compile_size = 32bit
    identifier = pumpkinhead.cu
    
        code for sm_20
            Function : _Z11simple_copyPfPKf
        /*0000*/     /*0x00005de428004404*/     MOV R1, c [0x1] [0x100];
        /*0008*/     /*0x98001c042c000000*/     S2R R0, SR_CTAid_Y;
        /*0010*/     /*0x88009c042c000000*/     S2R R2, SR_Tid_Y;
        /*0018*/     /*0x9400dc042c000000*/     S2R R3, SR_CTAid_X;
        /*0020*/     /*0x84011c042c000000*/     S2R R4, SR_Tid_X;
        /*0028*/     /*0x08001ca340000000*/     ISCADD R0, R0, R2, 0x5;
        /*0030*/     /*0x10309ca340000000*/     ISCADD R2, R3, R4, 0x5;
        /*0038*/     /*0x50001ca350004000*/     IMUL R0, R0, c [0x0] [0x14];
        /*0040*/     /*0x08009ca340000000*/     ISCADD R2, R0, R2, 0x5;
        /*0048*/     /*0x90201c4340004000*/     ISCADD R0, R2, c [0x0] [0x24], 0x2;
        /*0050*/     /*0x80209c4340004000*/     ISCADD R2, R2, c [0x0] [0x20], 0x2;
        /*0058*/     /*0x00001c8580000000*/     LD R0, [R0];
        /*0060*/     /*0x00201c8590000000*/     ST [R2], R0;
        /*0068*/     /*0x00001de780000000*/     EXIT;
            .....................................
    

    您确定所显示的代码是使用发行版设置编译的吗?

    此版本的CUDA使用了什么版本,以及使用了什么编译器选项来生成代码?我怀疑上面的SASS不是来自发行版,即代码不是通过完全优化生成的。我使用CUDA 5.5工具链,使用默认的编译器设置,为各种架构编译了上述代码,没有看到MOV指令。我将TILE_DIM定义为32。编译器可以将多行源代码编译成一行机器代码。如果在调试模式下发生这种情况,编译器将为未生成机器代码的源代码行插入额外的“no op”指令,以便为这些行提供断点位置。@njuffa非常感谢您的评论。您说的代码是在调试模式下编译的,这是对的。它是使用CUDA 5.0编译的。我已经在发布模式中编译了
    \uuuuu global\uuuuu
    函数,实际上微码看起来与我昨天发布的非常不同。请注意,新的微码现在已经由CUDA 5.5编译器获得(今天我从CUDA 5.0迁移到CUDA 5.5)。@RogerDahl感谢您的评论。在我的例子中,编译器是从寄存器
    RX
    向自身添加
    MOV
    指令,而不是
    NOP
    (无操作)指令。我已经在发布模式中编译了代码(参见我编辑的帖子),现在
    SM=2.1
    的版本显示了
    NOP
    指令,但我没有在调试模式中编译的代码中看到这些指令。非常感谢您的回答。事实上,代码是在调试模式下编译的。我在发布模式下编译时发布了微码,代码看起来与我昨天发布的代码非常不同,与您的代码非常相似。我不能完全复制你的,但也许这是因为我们使用的优化选项略有不同。