CUDAメモリ構造の.NETラッパーとして機能するクラス(以下の例を参照)
があり
、cudaMalloc()を使用して割り当てられ、IntPtrタイプのメンバーフィールドを使用して参照されます。
(クラスは、さまざまなCUDA機能をラップするネイティブC DLLのDllImportを使用します。)
disposeメソッドは、ポインターがIntPtr.Zeroであるかどうかを確認し、そうでない場合は
、メモリの割り当てを正常に解除して(CUDAの成功を返す)cudaFree()を
呼び出します。 IntPtr.Zero。
finalizeメソッドはdisposeメソッドを呼び出します。
問題は、disposeが以前に呼び出されていない状態でfinalizeメソッドが呼び出された
場合、cudaFree()関数が「無効なデバイスポインタ」のエラーコードを設定することです。
チェックしたところ、cudaFree()が受け取るアドレスは、cudaMalloc()によって返されたアドレスと同じであり、dispose()は以前に呼び出されていません。
dispose()への明示的な呼び出しを追加すると、同じアドレスが正常に解放されます。
私が見つけた唯一の回避策は、ファイナライザーからdisposeメソッドを呼び出さないことでしたが、dispose()が常に呼び出されるとは限らない場合、これによりメモリリークが発生する可能性があります。
なぜこれが起こるのか考えはありますか?-WindowsVista64ビット+GeForce8800およびWindowsXP32ビット+QuadroFXの.NET3.5SP1で、CUDA 2.2および2.3で同じ問題が発生しました(どちらの番号かはわかりません)。
クラスCudaEntity:IDisposable {{ プライベートIntPtrdataPointer; public CudaEntity() {{ // DllImportを介してcudaMalloc()を呼び出します。 //エラーコードを受け取り、0でない場合は期待値をスローします //this.dataPointerに値を割り当てます } public Dispose() {{ if(this.dataPointer!= IntPtr.Zero) {{ // DllImportを介してcudaFree()を呼び出します。 //エラーコードを受け取り、0でない場合は期待値をスローします this.dataPointer = IntPtr.Zero; } } 〜CudaEntity() {{ 廃棄(); } }
{{ //このコードは機能します var myEntity = new CudaEntity(); myEntity.Dispose(); }
{{ //このコードは「無効なデバイスポインタ」を引き起こします //ファイナライザーによるcudaFree()の呼び出しでエラーが発生しました var myEntity = new CudaEntity(); }