为了账号安全,请及时绑定邮箱和手机立即绑定

cudaMemcpy分段错误

cudaMemcpy分段错误

C++
慕娘9325324 2019-08-19 16:39:15
cudaMemcpy分段错误我已经被这个错误困扰了很长一段时间所以我决定在这里发布它。调用cudaMemcpy时发生此分段错误:CurrentGrid->cdata[i] = new float[size];cudaMemcpy(CurrentGrid->cdata[i], Grid_dev->cdata[i], size*sizeof(float),\                 cudaMemcpyDeviceToHost);CurrentGrid并且Grid_dev分别指向grid主机和设备上的类对象,在此上下文中i = 0。类成员cdata是一个浮点类型指针数组。为了调试,这cudaMemcpy调用之前对的,我打印出来的每个元素的值Grid_Dev->cdata[i],地址CurrentGrid->cdata[i]和Grid_dev->cdata[i]和的价值size,这一切看起来不错。但它仍然以“分段故障(核心转储)”结束,这是唯一的错误消息。cuda-memcheck只给出了“进程没有成功终止”。我目前无法使用cuda-gdb。关于去哪儿的任何建议?更新:现在看来我已经通过cudaMalloc解决了这个问题,设备上的另一个浮点指针A和cudaMemcpy的Grid_dev-> cdata [i]的值为A,然后是cudaMemcpy A来主机。所以上面写的代码段变成:float * A;cudaMalloc((void**)&A, sizeof(float));......cudaMemcpy(&A, &(Grid_dev->cdata[i]), sizeof(float *), cudaMemcpyDeviceToHost);    CurrentGrid->cdata[i] = new float[size];cudaMemcpy(CurrentGrid->cdata[i], A, size*sizeof(float), cudaMemcpyDeviceToHost);我之所以这样做是因为valgrind突然出现了“8号无效读取”,我认为这是指的Grid_dev->cdata[i]。我用gdb再次检查它,打印出Grid_dev->cdata[i]NULL值。所以我想即使在这个cudaMemcpy调用中也无法直接取消引用设备指针。但为什么 ?根据这个帖子底部的评论,我们应该能够在cudaMemcpy函数中取消引用设备指针。另外,我不知道cudaMalloc和cudaMemcpy如何工作的基本机制,但我认为cudaMalloc是一个指针,比如A,我们实际上指定这个指针指向设备上的某个地址。通过cudaMemcpy Grid_dev->cdata[i]到A,如上面的修改代码,我们重新分配指针A指向数组。那么,当它是cudaMalloced时,我们不会失去A指向的先前地址的轨道吗?这会导致内存泄漏吗?如果是的话,我应该如何妥善解决这种情况?谢谢!作为参考,我将完整函数的代码放在下面发生此错误的代码中。
查看完整描述

1 回答

?
弑天下

TA贡献1818条经验 获得超7个赞

我相信我知道问题是什么,但要确认它,看看你用来Grid_dev在设备上设置类的代码会很有用。

当要在设备上使用类或其他数据结构时,该类中有指针指向内存中的其他对象或缓冲区(可能在设备内存中,对于将在设备上使用的类),使这个顶级类在设备上可用的过程变得更加复杂。

假设我有一个这样的类:

class myclass{
  int myval;
  int *myptr;
  }

我可以在主机上实例化上面的类,然后malloc是一个数组,int并指定指针myptr,一切都会好的。要使此类仅在设备和设备上可用,过程可能类似。我可以:

  1. cudaMalloc指向将保持的设备内存的指针 myclass

  2. (可选)myclass使用cudaMemcpy将主机上的实例化对象复制到步骤1中的设备指针

  3. 在设备上,使用mallocnew分配设备存储myptr

如果我从不想访问myptr在主机上分配的存储空间,则上面的顺序很好。但如果我确实希望从主机可以看到该存储,我需要一个不同的序列:

  1. cudaMalloc是一个指向设备内存的指针myclass,让我们调用它mydevobj

  2. (可选)使用cudaMemcpy myclass将主机上的实例化对象复制到mydevobj步骤1中的设备指针

  3. 在主机上创建一个单独的int指针,让我们调用它 myhostptr

  4. cudaMalloc int存储在设备上myhostptr

  5. cudaMemcpy的指针值myhostptr从主机到设备的指针&(mydevobj->myptr)

之后,您可以cudaMemcpy通过嵌入指针指向myptr分配(通过cudaMalloc)的区域指向的数据myhostptr

请注意,在步骤5中,因为我正在获取此指针位置的地址,所以此cudaMemcpy操作仅需要mydevobj主机上的指针,该指针在cudaMemcpy操作中有效(仅限)。

myint然后将正确设置设备指针的值以执行您尝试执行的操作。如果你想要cudaMemcpy数据进出myint主机,你可以myhostptr在任何cudaMemcpy调用中使用指针,而不是 mydevobj->myptr。如果我们尝试使用mydevobj->myptr,则需要解除引用mydevobj,然后使用它来检索存储在其中的指针,myptr然后使用该指针作为复制到/来自位置。这在主机代码中是不可接受的。如果你试图这样做,你会得到一个seg错误。(注意,通过类比,我mydevobj就像你Grid_dev,我myptr就像你一样cdata

查看完整回答
反对 回复 2019-08-19
  • 1 回答
  • 0 关注
  • 671 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信