使用threadIdx的CUDA错误?
我想我碰到了一只库达虫。是否有人可以确认/注释代码(见下文) 代码(附件)将根据“BUG”定义产生不同的结果。当BUG=0时,结果是8(正确),而当BUG=1时,结果是4(错误)。代码的不同之处仅在于:使用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,我
#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;