2

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

4

2 回答 2

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 间接向我指出了这一点 :)

于 2013-09-25T13:34:21.603 回答
1

您可以将析构函数更改为:

~A() { cudaDeviceSynchronize(); cudaFree( dataOnGPU ... ); }

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

于 2013-09-25T12:55:04.023 回答