CUDA对象从设备复制到主机

时间:2018-04-20 17:45:39

标签: object cuda memcpy

我正在尝试将一个对象从设备复制回主机,并且它可以正常工作,但如果该对象包含一个指向某些东西的指针,我找不到正确的方法来调用cudaMemcpy。

这是一个简化的代码,用于显示我正在尝试做的事情。 cudaMemcpy返回cudaSuccess,但temp变量保持“空”。

class A {
public:
    int *s;
};

__global__ void MethodA(A *a) {
    printf("%d\n", a->s[2]);
}

int main() {
    A *a = new A();
    int asd[] = { 0, 1, 2, 3, 4 };
    a->s = asd;
    A *d_a;
    cudaMalloc((void**)&d_a, sizeof(A));
    cudaMemcpy(d_a, a, sizeof(A), cudaMemcpyHostToDevice);

    int * temp;
    cudaError e;
    e = cudaMalloc((void**)&temp, sizeof(int) * 5);
    e = cudaMemcpy(temp, a->s, sizeof(int) * 5, cudaMemcpyHostToDevice);
    e = cudaMemcpy(&(d_a->s), &temp, sizeof(int*), cudaMemcpyHostToDevice);

    MethodA << <1, 1 >> > (d_a);

    cudaMemcpy(a, d_a, sizeof(A), cudaMemcpyDeviceToHost);
    e = cudaMemcpy(&temp, a->s, sizeof(int) * 5, cudaMemcpyDeviceToHost);
    a->s = temp;

    cudaFree(d_a);
    delete(a);
    return 0;
}

1 个答案:

答案 0 :(得分:0)

问题在于:

e = cudaMemcpy(&(d_a->s), &temp, sizeof(int*), cudaMemcpyHostToDevice);

d_a是指向设备对象的指针,您无法在主机上取消引用它。 您必须先将s复制到设备,然后在主机上创建类型为A的对象,该对象具有指向s的设备副本的指针,然后复制设备上的这个对象。

这是CUDA的一个已知问题,经常发生链接列表或树木等结构,这是Nvidia为改进unified memory投入大量精力的原因之一。如果您可以使用它,并且它不会降低您的应用程序的性能,它可以为您节省很多这样的问题。

以下是修复问题的示例:

class A {
public:
    int *s;
};

__global__ void MethodA(A *a) {
    printf("%d\n", a->s[2]);
    a->s[2] = 6;
}

int main() {
    A *a = new A();
    int asd[] = { 0, 1, 2, 3, 4 };
    a->s = asd;

    A *a_with_d_s = new A();
    cudaMalloc(&(a_with_d_s->s), sizeof(int) * 5);
    cudaMemcpy(a_with_d_s->s, a->s, sizeof(int) * 5, cudaMemcpyHostToDevice);

    A *d_a;
    cudaMalloc(&d_a, sizeof(A));
    cudaMemcpy(d_a, a_with_d_s, sizeof(A), cudaMemcpyHostToDevice);

    MethodA << <1, 1 >> > (d_a);

    // note that if we call the following line, a->s will point to device
    // memory!
    //cudaMemcpy(a, d_a, sizeof(A), cudaMemcpyDeviceToHost);
    cudaMemcpy(a->s, a_with_d_s->s, sizeof(int) * 5, cudaMemcpyDeviceToHost);

    printf("%d\n", a->s[2]);

    cudaFree(d_a);
    cudaFree(a_with_d_s->s);

    delete(a);
    delete(a_with_d_s);
    return 0;
}

打印出来:

2
6