Nvidia CUDA-通过指针传递结构
我在将指向结构的指针传递给设备函数时遇到问题。 我想在本地内存中创建一个结构(我知道它很慢,这只是一个示例),然后通过指针将它传递给另一个函数。问题是,当我使用memcheck-on调试它时,会出现以下错误:Nvidia CUDA-通过指针传递结构,c,cuda,nvidia,memcheck,cuda-gdb,C,Cuda,Nvidia,Memcheck,Cuda Gdb,我在将指向结构的指针传递给设备函数时遇到问题。 我想在本地内存中创建一个结构(我知道它很慢,这只是一个示例),然后通过指针将它传递给另一个函数。问题是,当我使用memcheck-on调试它时,会出现以下错误: 程序收到信号CUDA\u异常\u 1,通道地址非法。 将焦点切换到CUDA内核0、网格1、块(0,0,0)、线程(0,0,0)、设备0、sm 7、扭曲0、通道0 测试时,foo中的0x0000000000977608(st=0x3fffc38)。cu:15 15 st->m_tx=99 如
程序收到信号CUDA\u异常\u 1,通道地址非法。
将焦点切换到CUDA内核0、网格1、块(0,0,0)、线程(0,0,0)、设备0、sm 7、扭曲0、通道0
测试时,foo中的0x0000000000977608(st=0x3fffc38)。cu:15
15 st->m_tx=99代码>
如果我在没有memcheck的情况下调试它,它工作得很好,并给出了预期的结果。
我的操作系统是RedHat 6.3 64位,内核为2.6.32-220。
我使用GTX680、CUDA 5.0并用sm=30编译程序
我用于测试的代码如下:
typedef struct __align__(8) {
int m_x0;
int m_tx;
} myStruct;
__device__ void foo(myStruct *st) {
st->m_tx = 99;
st->m_x0 = 123;
}
__global__ void myKernel(){
myStruct m_struct ;
m_struct.m_tx = 45;
m_struct.m_x0 = 90;
foo(&m_struct);
}
int main(void) {
myKernel <<<1,1 >>>();
cudaThreadSynchronize();
return 0;
}
typedef结构对齐(8){
int m_x0;
德克萨斯州国际大学;
}我的结构;
__设备无效foo(myStruct*st){
st->m_tx=99;
st->m_x0=123;
}
__全局_uu; void myKernel(){
myStruct mu struct;
m_struct.m_tx=45;
m_struct.m_x0=90;
foo&m_结构;
}
内部主(空){
myKernel();
cudaThreadSynchronize();
返回0;
}
有什么建议吗?谢谢您的帮助。编译器对您的示例代码进行了完全优化,因为所有代码都不会导致全局内存写入。通过将内核编译为cubin文件并使用cuobjdump
反汇编结果,可以很容易地证明这一点:
$ nvcc -arch=sm_20 -Xptxas="-v" -cubin struct.cu
ptxas info : Compiling entry function '_Z8myKernelv' for 'sm_20'
ptxas info : Function properties for _Z8myKernelv
0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Used 2 registers, 32 bytes cmem[0]
$ cuobjdump -sass struct_dumb.cubin
code for sm_20
Function : _Z8myKernelv
/*0000*/ /*0x00005de428004404*/ MOV R1, c [0x1] [0x100];
/*0008*/ /*0x00001de780000000*/ EXIT;
.............................
内核是完全空的。调试器无法调试要调查的代码,因为编译器/汇编器发出的代码中不存在该代码。如果我们对您的代码有一些自由:
typedef struct __align__(8) {
int m_x0;
int m_tx;
} myStruct;
__device__ __noinline__ void foo(myStruct *st) {
st->m_tx = 99;
st->m_x0 = 123;
}
__global__ void myKernel(int dowrite, int *output){
myStruct m_struct ;
m_struct.m_tx = 45;
m_struct.m_x0 = 90;
if (dowrite) {
foo(&m_struct);
output[threadIdx.x] = m_struct.m_tx + m_struct.m_x0;
}
}
int main(void) {
int * output;
cudaMalloc((void **)(&output), sizeof(int));
myKernel <<<1,1 >>>(1, output);
cudaThreadSynchronize();
return 0;
}
我们在汇编程序输出中得到实际代码。您在调试器中可能会更幸运。我来自CUDA开发人员工具团队。当编译用于设备端调试(例如,-G)时,原始代码将不会被优化。这个问题看起来像一个memcheck bug。谢谢你找到这个。我们将对此进行调查。您的设备代码将无法通过死代码删除,因为没有任何东西会导致写入全局内存。如果您在本例中看到的不是空内核,我会感到惊讶。我假设“CUDA 5.0”是指CUDA 5.0候选发行版(而不是早期预览版)?我刚刚测试了您的代码,它在memcheck中给出了相同的错误。问题可能是平台特定的,因为我无法在本地复制它(我用-g-g编译代码)。
$ nvcc -arch=sm_20 -Xptxas="-v" -cubin struct_dumb.cu
ptxas info : Compiling entry function '_Z8myKerneliPi' for 'sm_20'
ptxas info : Function properties for _Z8myKerneliPi
8 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Function properties for _Z3fooP8myStruct
0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Used 5 registers, 40 bytes cmem[0]
$ /usr/local/cuda/bin/cuobjdump -sass struct_dumb.cubin
code for sm_20
Function : _Z8myKerneliPi
/*0000*/ /*0x00005de428004404*/ MOV R1, c [0x1] [0x100];
/*0008*/ /*0x20105d034800c000*/ IADD R1, R1, -0x8;
/*0010*/ /*0x68009de218000001*/ MOV32I R2, 0x5a;
/*0018*/ /*0xb400dde218000000*/ MOV32I R3, 0x2d;
/*0020*/ /*0x83f1dc23190e4000*/ ISETP.EQ.AND P0, pt, RZ, c [0x0] [0x20], pt;
/*0028*/ /*0x00101c034800c000*/ IADD R0, R1, 0x0;
/*0030*/ /*0x00109ca5c8000000*/ STL.64 [R1], R2;
/*0038*/ /*0x000001e780000000*/ @P0 EXIT;
/*0040*/ /*0x10011c0348004000*/ IADD R4, R0, c [0x0] [0x4];
/*0048*/ /*0xc001000750000000*/ CAL 0x80;
/*0050*/ /*0x00009ca5c0000000*/ LDL.64 R2, [R0];
/*0058*/ /*0x84011c042c000000*/ S2R R4, SR_Tid_X;
/*0060*/ /*0x90411c4340004000*/ ISCADD R4, R4, c [0x0] [0x24], 0x2;
/*0068*/ /*0x0c201c0348000000*/ IADD R0, R2, R3;
/*0070*/ /*0x00401c8590000000*/ ST [R4], R0;
/*0078*/ /*0x00001de780000000*/ EXIT;
/*0080*/ /*0x8c00dde218000001*/ MOV32I R3, 0x63;
/*0088*/ /*0xec009de218000001*/ MOV32I R2, 0x7b;
/*0090*/ /*0x1040dc8590000000*/ ST [R4+0x4], R3;
/*0098*/ /*0x00409c8590000000*/ ST [R4], R2;
/*00a0*/ /*0x00001de790000000*/ RET;
...............................