gpt4 book ai didi

c++ - 在不同的 CUDA 内核中访问类成员

转载 作者:行者123 更新时间:2023-11-28 01:39:30 28 4
gpt4 key购买 nike

我有一个仅限 GPU 的类 T,我想在 GPU 上创建它,但在 CPU 上有一个引用,所以我可以将链接作为参数发送到不同的 CUDA 内核。

class T
{
public:
int v;
public:
__device__ T() { v = 10; }
__device__ ~T() {}
__device__ int compute() { return v; }
};

这是我用来创建类实例和调用 compute() 函数的内核。

__global__ void kernel(T* obj, int* out)
{
if(blockIdx.x * blockDim.x + threadIdx.x == 0) {
out[0] = obj->compute(); // no kernel error, but it returns garbage
}
}

__global__ void cudaAllocateGPUObj(T* obj)
{
if(blockIdx.x * blockDim.x + threadIdx.x == 0) {
obj = new T;
// if I call `out[0] = obj->compute();` here, everything works fine
}
}

main 函数简单地为 T* 类型的指针分配内存,稍后用作 cudaAllocateGPUObj 的参数。

int main()
{
int cpu, *gpu;
cudaMalloc((void**)&gpu, sizeof(int));
T* obj;
cudaMalloc((void**)&obj, sizeof(T*));
cudaAllocateGPUObj<<<1,1>>>(obj);
kernel<<<1,1>>>(obj, gpu);
cudaMemcpy(&cpu, gpu, sizeof(int), cudaMemcpyDeviceToHost);
cudaDeviceSynchronize();
printf("cudaMemcpy\nresult: %d\n", cpu);
return 0;
}

此代码的问题(如代码注释中所述)是当我在 cudaAllocateGPUObj 调用 out[0] = obj->compute(); 时code> kernel 并将得到的值传给CPU,一切正常。但是如果我想在另一个内核中获取成员值,它就会变成垃圾,尽管如果我将 v 变量的返回值更改为常量,一切正常。

你能告诉我这段代码有什么问题吗?

最佳答案

当您将参数传递给 CUDA 内核时,它是一种按值传递机制。您从指向对象的指针开始:

T* obj;

然后,不是为对象分配存储空间,而是为另一个指针分配存储空间:

cudaMalloc((void**)&obj, sizeof(T*));

所以我们走错了路。 (此时这是逻辑 C 编程错误。)接下来,在分配内核中,obj 参数(现在指向 GPU 内存空间中的某个位置)被按值<传递/strong>:

__global__ void cudaAllocateGPUObj(T* obj)
^^^ pass-by-value: local copy is made

现在,当你这样做时:

        obj = new T;

您创建一个新指针,并用该新指针覆盖obj 的本地拷贝。所以当然这在本地有效,但是调用环境中的 obj 拷贝不会使用该新指针进行更新。

解决此问题的一种可能方法是创建适当的指针对指针方法:

$ cat t5.cu
#include <stdio.h>

class T
{
public:
int v;
public:
__device__ T() { v = 10; }
__device__ ~T() {}
__device__ int compute() { return v; }
};

__global__ void kernel(T** obj, int* out)
{
if(blockIdx.x * blockDim.x + threadIdx.x == 0) {
out[0] = (*obj)->compute();
}
}

__global__ void cudaAllocateGPUObj(T** obj)
{
if(blockIdx.x * blockDim.x + threadIdx.x == 0) {
*obj = new T;
}
}

int main()
{
int cpu, *gpu;
cudaMalloc((void**)&gpu, sizeof(int));
T** obj;
cudaMalloc(&obj, sizeof(T*));
cudaAllocateGPUObj<<<1,1>>>(obj);
kernel<<<1,1>>>(obj, gpu);
cudaMemcpy(&cpu, gpu, sizeof(int), cudaMemcpyDeviceToHost);
cudaDeviceSynchronize();
printf("cudaMemcpy\nresult: %d\n", cpu);
return 0;
}

$ nvcc -arch=sm_35 -o t5 t5.cu
$ cuda-memcheck ./t5
========= CUDA-MEMCHECK
cudaMemcpy
result: 10
========= ERROR SUMMARY: 0 errors
$

关于c++ - 在不同的 CUDA 内核中访问类成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47835927/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com