首页 > 解决方案 > CUDA - 有没有办法在复制到 GPU 的同一内存中保留指向其他类的指针的相对性

问题描述

我正在使用代码,其中主机内存具有指向将由 cudaMemcpy 调用复制的其他内存区域的指针。

有没有办法在以下代码示例中执行类似的操作(这不起作用),以使设备内存指针中的元素与设备内存中的其他元素相对应,就像它们在主机内存中一样?还是有处理此类问题的“最佳实践”方式?

否则,我想我将不得不存储相对偏移量而不是指针。

#include "cuda_runtime.h"
#include <stdlib.h>
#include <stdio.h>

struct A {
    A* nextA = nullptr;
    int val = 5;
};
__global__ void kernel(A* d) {
    d[0].nextA->val = 20;
}
int main() {
    A* h = new A[2];
    h[0].nextA = &h[1];

    A* d;
    cudaMalloc(&d, sizeof(A) * 2);
    cudaMemcpy(d, h, sizeof(A) * 2, cudaMemcpyHostToDevice);
    kernel << <1, 1 >> > (d);
    cudaMemcpy(h, d, sizeof(A) * 2, cudaMemcpyDeviceToHost);

    printf("val=%d\n",h[1].val);    //hoping this would be 20
    return 0;
}

标签: cuda

解决方案


有没有办法......使设备内存指针中的元素与设备内存中的其他元素相对应,就像它们在主机内存中一样?

好吧,您可以使用 CUDA 的统一内存功能(自 CUDA 6 起可用),使用它您可以从主机端访问设备端内存,反之亦然。使用 Pascal 和更高版本的 GPU,您还可以获得虚拟内存分页,因此您可以分配比 GPU 实际拥有的更多的内存,并且仍然可以访问它。

当然,不经意地这样做会损害你的表现。非常小心地执行此操作仍会在某种程度上损害您的性能,而且我很难说有多少,因为这取决于用例,而且我不是 UVM + 分页类型的人。

还是有处理此类问题的“最佳实践”方式?

好吧,您可以使用偏移量而不是指针。您的相关指针可能共享某种常见的内存“竞技场”;如果他们还没有,您可能可以定义一个(在其中开始分配它们)。现在,停止存储指针。相反,将竞技场的基地址存储在某个公共位置,并从那里存储偏移量。然后在设备上分配竞技场大小的内存并复制您需要的内容。在设备端,您可以继续使用相同的代码,但使用设备端而不是主机端的 arena 地址。

...但实际上,这可能不是真正的答案。真正的答案很可能是:如果你经常取消引用指针,那么你的内核就有问题;重写它。它很可能被错误地设计为利用 GPU 的硬件,并且运行缓慢。


推荐阅读