【问题标题】:Copy an object to device?将对象复制到设备?
【发布时间】:2013-04-08 02:14:12
【问题描述】:

我可以将 C++ 对象复制到设备吗?

说我有:

class CudaClass
{
public:
int* data;
CudaClass(int x) {
    data = new int[1]; data[0] = x;
}
};

__global__ void useClass(CudaClass cudaClass)
{
    printf("%d" cudaClass.data[0]);
};


int main()
{
    CudaClass c(1);
}

现在如何将“c”复制到设备内存并启动内核“useClass”?

【问题讨论】:

    标签: cuda


    【解决方案1】:

    是的,您可以将对象复制到设备以在设备上使用。当对象嵌入了指向动态分配区域的指针时,该过程需要一些额外的步骤。

    请参阅my answer here 了解有关内容的讨论。该答案还链接了一些示例代码答案。

    此外,在您的类定义中,如果您希望某些功能在设备上可用,您应该适当地装饰这些功能(即可能使用__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);
        // create class storage on device and copy top level class
        CudaClass *d_c;
        cudaMalloc((void **)&d_c, sizeof(CudaClass));
        cudaMemcpy(d_c, &c, sizeof(CudaClass), cudaMemcpyHostToDevice);
        // make an allocated region on device for use by pointer in class
        int *hostdata;
        cudaMalloc((void **)&hostdata, sizeof(int));
        cudaMemcpy(hostdata, c.data, sizeof(int), cudaMemcpyHostToDevice);
        // copy pointer to allocated device storage to device class
        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),这是不允许的。

    【讨论】:

    • 好吧,再问一个问题:我看到的是您在设备上分配了一些内存,然后将指针值复制到对象内的数组中。为什么我不能直接为 myobject.array 分配而不是使用“中间”变量来保存数据并将其指针复制到 myobject.array 中?
    • 回复了这个问题并修改了我的答案。我相信我已经在链接答案之一之后发布的问题中解决了这个问题。
    • 非常感谢,非常明确的回答!如果可以的话,还有一个问题:为什么我不能在构造函数中做 CudaMalloc((void**)&data, 100*sizeof(int)) 而不是 data = new int[100] ?我认为应该直接在设备上分配而不是在主机上分配然后复制到设备。干杯
    • hostdata 包含指向设备内存的指针。但是&amp;hostdata 是指向主机内存中某个位置的指针。所以不,该指针不是“在设备上”,也没有指向“在设备上”的位置。 &amp;hostdata 指向主机内存中的一个位置。 hostdata 指向设备内存中的一个位置。
    • 对于这个问题中这个非常简单的类,唯一需要做的就是反转复制实际数据的cudaMemcpy 操作,因此,在内核之后,类似于:cudaMemcpy(c.data, hostdata, sizeof(int), cudaMemcpyDeviceToHost);。一个更复杂的对象可能需要几个步骤。由于从设备到主机的对象本身的直接副本会使对象中的嵌入指针无效,因此您需要一种方法来保留或“修复”这些指针,就像这个答案演示“修复”嵌入的指针一样在设备对象中。
    猜你喜欢
    • 2017-04-02
    • 2023-03-14
    • 1970-01-01
    • 2022-01-09
    • 2016-03-03
    • 1970-01-01
    • 1970-01-01
    • 2011-08-08
    • 1970-01-01
    相关资源
    最近更新 更多