使用threadIdx的CUDA错误?

使用threadIdx的CUDA错误?,cuda,nvcc,Cuda,Nvcc,我想我碰到了一只库达虫。是否有人可以确认/注释代码(见下文) 代码(附件)将根据“BUG”定义产生不同的结果。当BUG=0时,结果是8(正确),而当BUG=1时,结果是4(错误)。代码的不同之处仅在于: #if BUG unsigned int na=threadIdx.x, nb=threadIdx.y, nc=threadIdx.z; #else unsigned int na=0, nb=0, nc=0; #endif 我只提交了一个线程,所以在这两种情况下na==nb==nc==0,我

我想我碰到了一只库达虫。是否有人可以确认/注释代码(见下文)

代码(附件)将根据“BUG”定义产生不同的结果。当BUG=0时,结果是8(正确),而当BUG=1时,结果是4(错误)。代码的不同之处仅在于:

#if BUG
unsigned int na=threadIdx.x, nb=threadIdx.y, nc=threadIdx.z;
#else
unsigned int na=0, nb=0, nc=0;
#endif
我只提交了一个线程,所以在这两种情况下na==nb==nc==0,我还使用以下语句检查这一点:

assert( na==0 && nb==0 && nc==0 );
printf("INITIAL VALUES: %u %u %u\n",na,nb,nc);
以下是我的编译和运行:

nvcc -arch=sm_21 -DBUG=0 -o bug0 bug.cu
nvcc -arch=sm_21 -DBUG=1 -o bug1 bug.cu
./bug0
./bug1
nvcc:NVIDIA(R)Cuda编译器驱动程序版权所有(c)2005-2012 NVIDIA 公司成立于2012年9月21日星期五17:28:58\u PDT\u Cuda汇编 工具,5.0版,V0.2.1221

nvcc使用g++-4.6运行

最后是测试代码:

/* Compilation & run
   nvcc -arch=sm_21 -DBUG=0 -o bug0 bug.cu
   nvcc -arch=sm_21 -DBUG=1 -o bug1 bug.cu
   ./bug0
   ./bug1
 */

#include <stdio.h>
#include <assert.h>

__global__
void b(unsigned int *res)
{
#if BUG
    unsigned int na=threadIdx.x, nb=threadIdx.y, nc=threadIdx.z;
#else
    unsigned int na=0, nb=0, nc=0;
#endif

    assert( na==0 && nb==0 && nc==0 );
    printf("INITIAL VALUES: %u %u %u\n",na,nb,nc);

    unsigned int &iter=*res, na_max=2, nb_max=2, nc_max=2;
    iter=0;
    while(true)
    {
        printf("a-iter=%u     %u %u %u\n",iter,na,nb,nc);

        if( na>=na_max )
        {
            na  = 0;
            nb += blockDim.y;

            printf("b-iter=%u     %u %u %u\n",iter,na,nb,nc);

            if( nb>=nb_max )
            {
                printf("c-iter=%u     %u %u %u\n",iter,na,nb,nc);
                nb  = 0;
                nc += blockDim.z;
                if( nc>=nc_max )
                    break;  // end of loop
            }
            else
                printf("c-else\n");
        }
        else
            printf("b-else\n");

        printf("result    %u %u %u\n",na,nb,nc);
        iter++;

        na += blockDim.x;
    }
}

int main(void)
{
    unsigned int res, *d_res;
    cudaMalloc(&d_res,sizeof(unsigned int));
    b<<<1,1>>>(d_res);
    cudaMemcpy(&res, d_res, sizeof(unsigned int), cudaMemcpyDeviceToHost);
    cudaFree(d_res);

    printf("There are %u combinations (correct is 8)\n",res);

    return 0;
}
/*编译和运行
nvcc-arch=sm_21-DBUG=0-o bug0 bug.cu
nvcc-arch=sm_21-DBUG=1-o bug1 bug.cu
/错误0
/错误1
*/
#包括
#包括
__全球的__
无效b(无符号整数*res)
{
#如果BUG
无符号int na=threadIdx.x,nb=threadIdx.y,nc=threadIdx.z;
#否则
无符号整数na=0,nb=0,nc=0;
#恩迪夫
断言(na==0&&nb==0&&nc==0);
printf(“初始值:%u%u%u\n”,na、nb、nc);
无符号int&iter=*res,na_max=2,nb_max=2,nc_max=2;
iter=0;
while(true)
{
printf(“a-iter=%u%u%u%u\n”,iter,北美、北美、北美、北美);
如果(na>=na_max)
{
na=0;
nb+=blockDim.y;
printf(“b-iter=%u%u%u%u\n”,iter,北美,nb,北卡罗来纳州);
如果(nb>=nb_最大值)
{
printf(“c-iter=%u%u%u%u\n”,iter,北美,nb,北卡罗来纳州);
nb=0;
nc+=blockDim.z;
如果(nc>=nc\U最大值)
break;//循环结束
}
其他的
printf(“c-else\n”);
}
其他的
printf(“b-else\n”);
printf(“结果%u%u%u\n”,na、nb、nc);
iter++;
na+=blockDim.x;
}
}
内部主(空)
{
无符号整数res,*d_res;
cudaMalloc(&d_res,sizeof(unsigned int));
b(d_res);
cudaMemcpy(&res,d_res,sizeof(unsigned int),cudaMemcpyDeviceToHost);
库达弗里(d_res);
printf(“有%u个组合(正确的是8)\n”,res);
返回0;
}

这似乎是一个汇编程序错误。如果我举一个简化的例子:

template<int bug>
__global__
void b(unsigned int *res)
{
    unsigned int na, nb, nc;
    switch(bug) {
        case 1:
        na=threadIdx.x;
        nb=threadIdx.y;
        nc=threadIdx.z;
        break;

        default:
        na = nb = nc = 0;
        break;
    }

    unsigned int &iter=*res, na_max=2, nb_max=2, nc_max=2;
    iter=0;
    while(true)
    {
        if( na>=na_max )
        {
            na  = 0;
            nb += blockDim.y;

            if( nb>=nb_max )
            {
                nb  = 0;
                nc += blockDim.z;
                if( nc>=nc_max ) break;
            }
        }

        iter++;
        na += blockDim.x;
    }
}
然而,汇编程序的输出是另一回事(同样地,左边是
bug=0
,右边是
bug=1
):

右边的代码缺少两条
SSY
指令,运行它会导致内核处于无限循环中,这与某种SIMT正确性问题是一致的,比如未检测到的分支发散或同步障碍周围的发散。真正有趣的是,当在单个块中只运行单个线程时,它会挂起


我建议如果我是你,就在英伟达注册开发者网站上提交bug报告。我已经提交了它(问题参考#130418-000028),但我没有看到NVidia团队的任何反应,所以我决定将它发送到这里。StackOverflow识别问题的速度更快!
.visible .entry _Z1bILi0EEvPj(                         .visible .entry _Z1bILi1EEvPj(
        .param .u64 _Z1bILi0EEvPj_param_0                      .param .u64 _Z1bILi1EEvPj_param_0
        )                                                      )
{                                                      {
    .reg .pred  %p<4>;                                     .reg .pred   %p<4>;
    .reg .s32   %r<28>;                                    .reg .s32    %r<28>;
    .reg .s64   %rd<3>;                                    .reg .s64    %rd<3>;


    ld.param.u64    %rd2, [_Z1bILi0EEvPj_param_0];         ld.param.u64     %rd2, [_Z1bILi1EEvPj_param_0];
    cvta.to.global.u64  %rd1, %rd2;                        cvta.to.global.u64   %rd1, %rd2;
    mov.u32     %r26, 0;                                   .loc 2 11 1
    .loc 2 22 1                                                mov.u32  %r27, %tid.x;
        st.global.u32   [%rd1], %r26;                      .loc 2 12 1
    .loc 2 33 1                                                mov.u32  %r25, %tid.y;
        mov.u32     %r1, %ntid.z;                          .loc 2 13 1
    .loc 2 28 1                                                mov.u32  %r26, %tid.z;
        mov.u32     %r2, %ntid.y;                          mov.u32  %r24, 0;
    .loc 2 39 1                                            .loc 2 22 1
        mov.u32     %r3, %ntid.x;                              st.global.u32    [%rd1], %r24;
    mov.u32     %r27, %r26;                                .loc 2 33 1
    mov.u32     %r25, %r26;                                    mov.u32  %r4, %ntid.z;
    mov.u32     %r24, %r26;                                .loc 2 28 1
                                                               mov.u32  %r5, %ntid.y;
BB0_1:                                                     .loc 2 39 1
    .loc 2 25 1                                                mov.u32  %r6, %ntid.x;
        setp.lt.u32     %p1, %r27, 2;                  
    @%p1 bra    BB0_4;                                 BB1_1:
                                                           .loc 2 25 1
    .loc 2 28 1                                                setp.lt.u32  %p1, %r27, 2;
        add.s32     %r25, %r2, %r25;                       @%p1 bra     BB1_4;
    .loc 2 30 1                                        
        setp.lt.u32     %p2, %r25, 2;                      .loc 2 28 1
    mov.u32     %r27, 0;                                       add.s32  %r25, %r5, %r25;
    .loc 2 30 1                                            .loc 2 30 1
        @%p2 bra    BB0_4;                                     setp.lt.u32  %p2, %r25, 2;
                                                           mov.u32  %r27, 0;
    .loc 2 33 1                                            .loc 2 30 1
        add.s32     %r26, %r1, %r26;                           @%p2 bra     BB1_4;
    .loc 2 34 1                                        
        setp.gt.u32     %p3, %r26, 1;                      .loc 2 33 1
    mov.u32     %r27, 0;                                       add.s32  %r26, %r4, %r26;
    mov.u32     %r25, %r27;                                .loc 2 34 1
    .loc 2 34 1                                                setp.gt.u32  %p3, %r26, 1;
        @%p3 bra    BB0_5;                                 mov.u32  %r27, 0;
                                                           mov.u32  %r25, %r27;
BB0_4:                                                     .loc 2 34 1
    .loc 2 38 1                                                @%p3 bra     BB1_5;
        add.s32     %r24, %r24, 1;                     
    st.global.u32   [%rd1], %r24;                      BB1_4:
    .loc 2 39 1                                            .loc 2 38 1
        add.s32     %r27, %r3, %r27;                           add.s32  %r24, %r24, 1;
    bra.uni     BB0_1;                                     st.global.u32    [%rd1], %r24;
                                                           .loc 2 39 1
BB0_5:                                                         add.s32  %r27, %r6, %r27;
    .loc 2 41 2                                            bra.uni  BB1_1;
        ret;                                           
}                                                      BB1_5:
                                                           .loc 2 41 2
                                                               ret;
                                                       }
    /*0008*/    MOV R1, c [0x0] [0x44];                MOV R1, c [0x0] [0x44];              
    /*0010*/    MOV R6, c [0x0] [0x140];               MOV R6, c [0x0] [0x140];
    /*0018*/    MOV R7, c [0x0] [0x144];               MOV R7, c [0x0] [0x144];
    /*0020*/    S2R R0, SR_Tid_X;                      MOV R0, RZ;
    /*0028*/    MOV R4, RZ;                            MOV R2, RZ;
    /*0030*/    S2R R3, SR_Tid_Z;                      MOV R3, RZ;
    /*0038*/    ST.E [R6], RZ;                         MOV R4, RZ;
    /*0048*/    S2R R2, SR_Tid_Y;                      ST.E [R6], RZ;
    /*0050*/    ISETP.LT.U32.AND P0, pt, R0, 0x2, pt;  ISETP.LT.U32.AND P0, pt, R2, 0x2, pt;
    /*0058*/    SSY 0xd0;                              @P0 BRA 0xb0;
    /*0060*/    @P0 BRA 0xc0;                          IADD R3, R3, c [0x0] [0x2c];
    /*0068*/    IADD R2, R2, c [0x0] [0x2c];           MOV R2, RZ;
    /*0070*/    MOV R0, RZ;                            ISETP.LT.U32.AND P0, pt, R3, 0x2, pt;
    /*0078*/    ISETP.LT.U32.AND P0, pt, R2, 0x2, pt;  @P0 BRA 0xb0;
    /*0088*/    SSY 0xa0;                              IADD R0, R0, c [0x0] [0x30];
    /*0090*/    @P0 BRA 0xc0;                          MOV R2, RZ;
    /*0098*/    IADD.S R3, R3, c [0x0] [0x30];         ISETP.GT.U32.AND P0, pt, R0, 0x1, pt;
    /*00a0*/    ISETP.GT.U32.AND P0, pt, R3, 0x1, pt;  MOV R3, RZ;
    /*00a8*/    MOV R0, RZ;                            @P0 EXIT;
    /*00b0*/    MOV R2, RZ;                            IADD R4, R4, 0x1;
    /*00b8*/    @P0 EXIT;                              IADD R2, R2, c [0x0] [0x28];
    /*00c8*/    IADD.S R4, R4, 0x1;                    ST.E [R6], R4;
    /*00d0*/    ST.E [R6], R4;                         BRA 0x50;
    /*00d8*/    IADD R0, R0, c [0x0] [0x28];           BRA 0xd8;
    /*00e0*/    BRA 0x50;                              NOP CC.T;
    /*00e8*/    BRA 0xe8;                              NOP CC.T;
    /*00f0*/    NOP CC.T;                              NOP CC.T;
    /*00f8*/    NOP CC.T;                              NOP CC.T;