是的,您可以将对象复制到设备上以在设备上使用。当对象具有指向动态分配区域的嵌入式指针时,该过程需要一些额外的步骤。
请参见我在这里的答案,了解有关所涉及内容的讨论。该答案还链接了一些示例代码答案。
另外,在类定义中,如果您希望某些函数在设备上可用,您应该适当地装饰这些函数(即可能使用__device__ __host__
);
编辑:针对一个提问(现已删除),以下是我根据提供的代码能想到的最简单的示例代码:
#include <stdio.h>
class CudaClass
{
public:
int* data;
CudaClass(int x) {
data = new int[1]; data[0] = x;
}
};
__global__ void useClass(CudaClass *cudaClass)
{
printf("%d\n", cudaClass->data[0]);
};
int main()
{
CudaClass c(1);
CudaClass *d_c;
cudaMalloc((void **)&d_c, sizeof(CudaClass));
cudaMemcpy(d_c, &c, sizeof(CudaClass), cudaMemcpyHostToDevice);
int *hostdata;
cudaMalloc((void **)&hostdata, sizeof(int));
cudaMemcpy(hostdata, c.data, sizeof(int), cudaMemcpyHostToDevice);
cudaMemcpy(&(d_c->data), &hostdata, sizeof(int *), cudaMemcpyHostToDevice);
useClass<<<1,1>>>(d_c);
cudaDeviceSynchronize();
return 0;
}
为了简明扼要,我没有使用通常的cuda错误检查。
回答这个问题,你不能直接使用设备类中的指针从主机分配存储空间。这是因为cudaMalloc需要一个普通的基于主机的指针存储,比如你用以下方式获得的指针:
int *hostdata;
如果指针的存储已经在设备上,则cudaMalloc无法使用该指针。以下代码将无法运行:
cudaMalloc(&(d_c->data), sizeof(int));
因为在主机代码中对设备指针(d_c)进行解引用是不允许的。
hostdata
包含指向设备内存的指针。但是,&hostdata
是指向主机内存位置的指针。因此,这个指针并不在设备上,并且它也不指向设备上的位置。&hostdata
指向主机内存中的一个位置,而hostdata
则指向设备内存中的一个位置。 - Robert CrovellacudaMemcpy
操作,因此,在内核之后,类似于:cudaMemcpy(c.data, hostdata, sizeof(int), cudaMemcpyDeviceToHost);
。更复杂的对象可能需要几个步骤。由于直接从设备返回主机的对象本身的复制将使对象中的嵌入指针无效,因此您需要一种方法来保留或“修复”这些指针,就像这个答案演示了如何“修复”设备对象中的嵌入指针一样。 - Robert Crovellad_c->data
上使用cudaFree
?我正在考虑将其放在CudaClass
的析构函数中。假设我的CudaClass
还有许多标量整数和双精度浮点数(约为百个),我是否也需要释放它们? - rinkertmalloc()
、new
、cudaMalloc
、cudaMallocManaged
等。相应的解除分配器是free()
、delete
和cudaFree
。如果这还不清楚,请提出一个新问题。我没有试图编写生产就绪的代码。除非问题涉及到它,否则我通常不这样做。 - Robert Crovella