考虑我的问题的这个简化版本:为了将数据传递给CUDA内核,我使用了一个保存数据的类和一个指向图形硬件上数据的指针。
class A {
int data;
float* dataOnGPU;
A() { cudaMalloc( dataOnGPU ... ); }
~A() { cudaFree( dataOnGPU ... ); }
};
void myFunction()
{
A obj;
kernelCall1<<<1,1>>>( obj );
kernelCall2<<<1,1>>>( obj ); // obj.dataOnGPU no longer points to valid memory
}
返回第一个内核调用的结果是调用obj副本的析构函数(因为内核是通过值调用的,这会创建一个副本)。这为obj及其副本释放dataOnGPU。在obj超出范围之前,obj.dataOnGPU的内存不应该是空闲的。
当然,有可能避免这种情况,但我希望有一个漂亮而干净的RAII行为。有什么建议吗?
答案 0 :(得分:2)
使用自定义复制构造函数是解决方案:
class A {
int data;
float* dataOnGPU;
bool isCopy;
A() { cudaMalloc( dataOnGPU ... ); isCopy = false; }
A( const A& _orig ) { *this = _orig; isCopy = true; }
~A() { if (!isCopy) cudaFree( dataOnGPU ... ); }
};
void myFunction()
{
A obj;
kernelCall1<<<1,1>>>( obj );
kernelCall2<<<1,1>>>( obj ); // obj.dataOnGPU still points to valid memory
}
感谢Paul R间接指出我:)
答案 1 :(得分:1)
您可以将析构函数更改为:
~A() { cudaDeviceSynchronize(); cudaFree( dataOnGPU ... ); }
以便在释放内存之前内核运行完毕。