从 CUDA 中的主机访问设备上的类成员数组指针
Posted
技术标签:
【中文标题】从 CUDA 中的主机访问设备上的类成员数组指针【英文标题】:Accessing Class Member Array Pointer on Device from Host in CUDA 【发布时间】:2012-12-25 02:02:30 【问题描述】:我已经被这个问题难住了一段时间了。这涉及到 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 空闲操作:无效参数”)。我已经尝试了很多这样的变体,包括使用 hc->array,但没有成功。有没有什么方法可以让我得到这个数组,而不必编写一个内核函数来复制每个单独的条目?我正在使用 CUDA 5.0。
【问题讨论】:
类中的设备指针(即MyClass.array
的值)是使用主机API还是使用设备内核内部的malloc/new
分配的?
指针是使用主机 API 分配的。在我读入输入后,我在主机上分配了一个数组,在设备上分配了另一个数组(使用 cudaMalloc)。我将一些初始值存储到主机数组,然后使用 cudaMemCpy 将此信息复制到设备数组上。然后我使用一个简单的 >> 内核将 MyClass.array 的值设置为设备数组。之后我释放了主机阵列,因为我不再需要它了。
dc
是指向设备内存的指针。你不能像这样在主机上尊重它dc->array
考虑到这一点,我建议您重新考虑解决问题的方式。首先,使用结构/类的数组比使用数组的结构/类更简单(但不一定更有效)(在这种情况下,数组无论如何都必须具有固定的大小)。
【参考方案1】:
我认为您以错误的方式使用 sizeof
和指针。
您的代码中的sizeof(dc)
和sizeof(dc->array)
可以替换为sizeof(MyClass)
和ArraySize * sizeof(int)
。
对于指针,您必须执行两次cudaMemcpy
才能获取您的数组。
首先获取对象hc,它存储了你的数组的addr。
cudaMemcpy(&hc, dc, sizeof(MyClass), cudaMemcpyDeviceToHost);
然后获取数组本身。
cudaMemcpy(h_array, hc.array, ArraySize*sizeof(int),D2H);
另外,dc
是指向设备内存的指针。你不能像这样在主机上取消引用它dc->array
【讨论】:
这种帮助!虽然您的方法不适用于我的原始代码,但它确实让我想到更改 MyClass 对象的初始化方式。最初它被设置为在我将其复制到设备后接收设备指针,但我将其更改为在将其复制到设备之前给它指针。无论出于何种原因,虽然我在拥有类的原始主机副本时仍然可以访问该数组,但是当我将它从设备复制回来时,指针不再起作用(导致相同的错误)。 @C.G.真奇怪。存储在array
中的值(在本例中为地址)在复制到设备内存并从设备内存复制回来后不应更改。
@C.G.我认为您的代码中的sizeof(dc)
和sizeof(dc->array)
也可能是一个问题。改用sizeof(MyClass)
& ArraySize*sizeof(int)
。
是的,这就是问题所在。从 sizeof(dc) 切换到 sizeof(MyClass) 解决了它。感谢您的帮助!以上是关于从 CUDA 中的主机访问设备上的类成员数组指针的主要内容,如果未能解决你的问题,请参考以下文章