cuda中结构体指针传输问题

初学cuda,需要传递包含指针的结构体至核函数,但结构体的指针成员拷贝至显存总是无法成功。废话不多说,测试代码如下。望解答。 代码中第三步最后的拷贝,packet_dev的指针成员总是为空。。。为什么呢!? 对了,系统是linux64位。

strcut PKT
{
char *a;
char *b;
};

int main()
{
/* 第一步,初始化host变量 */
struct PKT packet;
packet.a = (char *)malloc(10);
memset(packet.a,‘a’,9);
packet.b = (char *)malloc(10);
memset(packet.b,‘b’,9);

/* 第二步,设置中间变量 */
struct PKT packet_t;
cudaMalloc((void **)&packet_t.a,10);
cudaMalloc((void **)&packet_t.b,10);
cudaMemcpy(packet_t.a,packet.a,10,cudaMemcpyHostToDevice);
cudaMemcpy(packet_t.b,packet.b,10,cudaMemcpyHostToDevice);

/* 第三步,申请device空间,拷贝host数据至device */
struct PKT *packet_dev;
cudaMalloc((void **)&packet_dev,sizeof(struct PKT));
cudaMemcpy(packet_dev,&packet_t,sizeof(struct PKT),cudaMemcpyHostToDevice);

return 0;
}

废话同样不多说,

您的代码无问题(除了struct写成了strcut)!

为何你认为有问题呢?可能是你观察错误!
(请用nsight观察device memory, 而不是直接用VS开始调试,然后用鼠标移动到packet_dev上观察!)

您可以直接从您的kernel中输出p->a指向的那堆东西,看看是不是’a’…

以及类似的,您可以看p->b指向的那堆东西,是不是’b’

(我已经试验了,无问题的)

我来稍微补充一下:

横扫斑竹已经实测LZ的代码是无问题的,在此基础上,如果LZ只是想让kernel得到这个结构体的内容,那么可以直接将此结构体作为kernel函数的参数使用即可,这样比较简洁,效能也好。

祝您编码顺利~

代码辛苦重新手打的。还没用过nsight。。。 我是用gdb观察了下,发现packet_dev的成员指针总为空,并加入下面的测试语句,程序报错,,所以才认为拷贝方式有错,并没有实际拷贝成功。

我加入过如下测试语句:
char r[10] = {0};

cudaMemcpy(r,packet_dev->a,9,cudaMemcpyDeviceToHost);

:报错,packet_dev->a 空指针。

不过还是相信版主,再去重新思考测试下。

LZ您好:

您的前面的用法确实是无问题的,如果报错,请您逐步调试检查一下,每步看看返回值什么的。

以及,您5#给出的一句代码里面使用了全角的逗号,如果这个是您直接粘贴过来的代码,请您修正为半角的英文逗号。

大致如此,祝您好运~

因为某种原因,代码都重新手打的。。。 :cry: 编译是没错的

不过还是相信各位版主,自己回去再仔细看下。
另外问下 这个nsignt可以在linux的命令行下使用么? 因为某种原因,无法在图形界面下工作。

多谢!

LZ您好:

nsight可以在VS下使用(使用VS的对应版本)以及可以在eclipse下使用(使用eclipse对应的版本)。

您前面的代码部分经横扫斑竹在VS下测试并使用nsight查看对应指针是无误的。
您也可以考虑下各个步骤是否都成功了,而不是单纯看kernel。

祝您编码顺利~

[

各位版主:
晚上好!
在我的环境中依然有错,我的系统是linux64位的,网络上找了些资料,怀疑有可能是字节对齐的问题。麻烦各位版主copy下代码找下原因。
多谢多谢!
手工输入代码如下:

#include <stdio.h>

struct PKT
{
char *a;
char *b;
};

int main()
{
/* 1:初始化host数据 */
struct PKT packet;
packet.a = (char *)malloc(10);
memset(packet.a,‘a’,9);
packet.b = (char *)malloc(10);
memset(packet.b,‘b’,9);

/* 2: */
struct PKT packet_tmp;
cudaMalloc((void **)&packet_tmp.a,10);
cudaMalloc((void **)&packet_tmp.b,10);

/* 3 :有打印信息,验证host数据确实拷贝进显存 */
cudaMemcpy(packet_tmp.a,packet.a,10,cudaMemcpyHostToDevice);
cudaMemcpy(packet_tmp.b,packet.b,10,cudaMemcpyHostToDevice);
char aa[10] = {0},bb[10] = {0};
cudaMemcpy(aa,packet_tmp.a,9,cudaMemcpyDeviceToHost);
cudaMemcpy(bb,packet_tmp.b,9,cudaMemcpyDeviceToHost);
printf(“aa = %s,bb = %s\n”,aa,bb);

/* 4:拷贝整个结构体 */
struct PKT *packet_dev;
cudaMalloc((void **)&packet_dev,sizeof(struct PKT));
cudaMemcpy(packet_dev,&packet_tmp,sizeof(struct PKT),cudaMemcpyHostToDevice);

/* 5:出错了。。。packet_dev->a 为空指针 */
char *r_val = (char *)malloc(10);
cudaMemcpy(r_val,packet_dev->a,9,cudaMemcpyDeviceToHost);

printf(“char a = %s\n”,r_val);

return 0;

}

我都告诉你没任何问题了,你在那里瞎测试神马??

你可以无视我的话,可以继续乱测试,但你不能来论坛乱扯!

我前文说的很清楚了,您的1#代码无问题,你认为“有问题”,实际上你是乱观察,将没事的当成了有事的。

人家本来好好的,你乱测试(实际上你的测试代码有问题,原文没问题!)

我不想说什么了。

请ICE补充吧。

LZ您好:

我来向您稍微解释下前面的问题:

1:您1#给出的用法是正确的,以及我和横扫斑竹已经多次向您指出了这一点。

2:“1:”的正确性您可以使用nsight等可以调试kernel代码的工具,予以检测。

3:您的困扰实际上来自于您的测试方法,根据您9#的代码,我们发现
cudaMemcpy(r_val,packet_dev->a,9,cudaMemcpyDeviceToHost);
这一句是有误的。
请将“packet_dev->”改为“packet_tmp.a”即可。

因为cudaMemcpy要求各参数都是host端的,您packet_dev指向了device端的结构体,这样cudaMemcpy就需要使用device端的结构体的成员(在device端的global memory上)作为参数了,这是不被允许的。

所以,如果您只能使用目前的copy——print方式检查的话,请修改上述参数。

大致如此,祝您编码愉快~

[

懂了。
多谢热心的版主。