[英]Accessing Class Member in different CUDA kernels
我有一个仅在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;
}
这段代码的问题(在代码的注释中指定)是当我调out[0] = obj->compute();
在cudaAllocateGPUObj
内核中并将获取的值传输到CPU,一切都正确。 但是,如果我想在另一个内核中获取成员值,它将变成垃圾,尽管如果我将返回值从v
变量更改为常量,则一切正常。
您能告诉我这段代码有什么问题吗?
当您将参数传递给CUDA内核时,它是一种按值传递机制。 您已经从指向对象的指针开始:
T* obj;
然后,不为该对象分配存储,而是为另一个指针分配存储:
cudaMalloc((void**)&obj, sizeof(T*));
所以我们在这里走错了路。 (这是逻辑C编程错误。)接下来,在分配内核中, obj
参数(现在指向GPU内存空间中的某个位置)通过值传递:
__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
$
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.