在CUDA中,如何从主机访问设备上的类成员数组指针?

3

我对这个问题感到很困惑已经一段时间了。这涉及CUDA设备指针。我有一个自定义类的实例,它位于我的设备上,并且它有一个成员变量,它是指向一个数组的指针(该数组也在设备上)。

class MyClass {
public:
    int* array;
    // Other variables and functions, etc.
};

需要使用动态分配数组,因为数组的大小取决于程序开始时的某些输入。在程序运行期间,我正在使用内核函数修改类,但最终我希望在主机上获取此类的副本以输出到文件。然而,我似乎无法让cudaMemCpy为我工作。
我可以使用以下代码(其中dc是指向设备上类的指针)来获取类的副本:
MyClass hc;
cudaMemcpy(&hc, dc, sizeof(dc), cudaMemcpyDeviceToHost);

但是这只能获取不是指针的类中的信息,这是有道理的,因为在 hc 中检索到的指针仍将指向设备上的数据。所以我想我可以使用此代码来实际获取该数组。
int* h_array;
cudaMemcpy(h_array, dc->array, sizeof(dc->array), cudaMemcpyDeviceToHost);

这只返回一个空数组,而且我得到了一个cudaFree错误(“Cuda错误:cuda free操作:无效参数”)。我尝试了很多变化,包括使用hc->array,但都没有成功。有没有办法可以在不必编写内核函数复制每个单独条目的情况下获取此数组?我正在使用CUDA 5.0。


设备指针在类中(即MyClass.array的值)是使用主机API分配还是在设备上的内核中使用malloc/new分配的? - talonmies
指针是使用主机API分配的。在读取输入后,我在主机上分配了一个数组和另一个设备上的数组(使用cudaMalloc)。我将一些初始值存储到主机数组中,然后使用cudaMemCpy将此信息复制到设备数组中。然后,我使用简单的<<<1,1>>>内核将MyClass.array的值设置为设备数组。之后,我释放主机数组,因为我不再需要它。 - C.G.
dc是指向设备内存的指针。你不能在主机上像这样解引用它,即dc->array - kangshiyin
考虑到这一点,我建议您重新思考解决问题的方式。首先,使用结构体/类的数组比使用数组的结构体/类更简单(但不一定更有效),在后一种情况下,数组仍然必须具有固定的大小。 - sandeep.ganage
1个回答

1

我认为你在使用sizeof和指针方面存在问题。

你代码中的sizeof(dc)sizeof(dc->array)可以被替换为sizeof(MyClass)ArraySize * sizeof(int)

对于指针,你需要执行两次cudaMemcpy才能获取到你的数组。

  1. 首先获取对象hc,它存储了数组的地址。

    cudaMemcpy(&hc, dc, sizeof(MyClass), cudaMemcpyDeviceToHost);
    
  2. 然后获取数组本身。

    cudaMemcpy(h_array, hc.array, ArraySize*sizeof(int),D2H);
    
此外,dc 是指向设备内存的指针。您不能在主机上像这样对其进行解引用 dc->array

这有点帮助!虽然您的方法对我的原始代码没有起作用,但它让我想到了改变MyClass对象初始化的方式。最初,它被设置为在将设备指针复制到设备后接收它,但我将其更改为在将其复制到设备之前给它指针。不过,出于某种原因,当我拥有类的原始主机副本时仍然可以访问数组,但是当我从设备上将其复制回来时,指针就不再起作用了(导致相同的错误)。 - C.G.
@C.G. 这很奇怪。在将 array 复制到设备内存中并从设备内存中复制回来后,存储在其中的值(例如 addr)不应该更改。 - kangshiyin
@C.G. 我认为你代码中的 sizeof(dc)sizeof(dc->array) 也可能是个问题。尝试使用 sizeof(MyClass)ArraySize*sizeof(int) - kangshiyin
是的,那就是问题所在。从 sizeof(dc) 切换到 sizeof(MyClass) 解决了它。感谢您的帮助! - C.G.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接