0

我有以下全局内核:

__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

据我了解,该错误是由于无效地址引起的。
谁能帮我解决这个问题?谢谢

4

2 回答 2

1

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

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

因为,使用内核分配new会创建一个指向设备堆的指针,所以这样的指针不能用于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();
}

请注意,我尚未编译和测试此代码,因此可能会出现错误,但这概述了我认为可行的方法。你可能也对我对这个问题的回答感兴趣

于 2013-02-26T21:18:11.220 回答
1

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

于 2013-02-26T21:12:08.323 回答