使用new和double指针在全局内核中创建一个类对象

时间:2013-02-26 19:12:00

标签: cuda

我有以下全局内核:

__global__ void pdegpu(PDE_ParabolicD1_Num_GPU **pdes)
{    
    PDE_ParabolicD1_Num_GPU *loc;
    loc = new PDE_ParabolicD1_Num_GPU();
    loc->Setup();
    delete loc;
    //above code was just an example to show that new and delete work fine

    *pdes = new PDE_ParabolicD1_Num_GPU();   //error occurs here
    (*pdes)->Setup();
}

我打电话来创建PDE_ParabolicD1_Num_GPU类型的对象并进行设置。在main()中,我将使用相同的对象,这就是我在函数参数中使用双指针的原因。 在main()中,我执行以下操作:

PDE_ParabolicD1_Num_GPU pdes_host;
PDE_ParabolicD1_Num_GPU *pdes_dev=0;
pdegpu<<<1,1>>>(&pdes_dev);
cudaStatus = cudaMemcpy(&pdes_host, pdes_dev, sizeof(PDE_ParabolicD1_Num_GPU), cudaMemcpyDeviceToHost);
...
delete [] pdes_dev;

但是,我在代码中显示错误,并且错误的CUDA Memory Checker输出如下:

Memory Checker detected 1 access violations.
error = access violation on store (global memory)
gridid = 16
blockIdx = {0,0,0}
threadIdx = {0,0,0}
address = 0x0018f420
accessSize = 4
error MemoryChecker: #misaligned=0  #invalidAddress=1

据我所知,错误是由于invalidAddress造成的 任何人都可以帮我解决这个问题吗?  谢谢

2 个答案:

答案 0 :(得分:1)

您应首先通过cudaMalloc分配内存。目前您的设备代码正在尝试写入主机内存。

答案 1 :(得分:1)

pdes_dev是主机指针。设备代码无法访问主机指针。如果要创建可在设备上修改的指针,请执行以下操作:

PDE_ParabolicD1_Num_GPU **pdes_dev=0;
cudaMalloc((void ***) &(pdes_dev), sizeof(PDE_ParabolicD1_Num_GPU *));
pdegpu<<<1,1>>>(pdes_dev);

因为,使用in-kernel new分配会创建一个指向device heap的指针,这样的指针不能用于cudaMemcpy操作,以将存储在那里的数据返回给主机。然后,您必须执行设备到设备复制,以将内核修改的数据移动到适合传输回主机的缓冲区中。因此,更好的方法可能是从主机为对象分配设备存储空间:

PDE_ParabolicD1_Num_GPU *pdes_dev=0;
cudaMalloc((void **) &(pdes_dev), sizeof(PDE_ParabolicD1_Num_GPU));
pdegpu<<<1,1>>>(pdes_dev);

您的内核代码必须相应更改:

__global__ void pdegpu(PDE_ParabolicD1_Num_GPU *pdes)
{    

    pdes->Setup();
}

请注意,我没有编译和测试此代码,因此可能存在错误,但这概述了我认为可行的方法。您可能对我对this question

的回答感兴趣