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.dataOnGPU のメモリは、obj が範囲外になるまで解放されません。

もちろん、これを回避する可能性はありますが、私は素敵でクリーンな 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 に答える