在CUDA中调用内核后阻止析构函数调用

时间:2013-09-25 12:47:55

标签: cuda raii

考虑我的问题的这个简化版本:为了将数据传递给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行为。有什么建议吗?

2 个答案:

答案 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 ... ); }

以便在释放内存之前内核运行完毕。