2013-09-25 33 views
2

Considere我的問題的這種簡化版本內核調用後預防析構函數調用:將數據傳遞到一個CUDA內核,我用它保存數據和指向上的圖形設備數據的類。在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行爲。有什麼建議麼?

回答

1

你可以你的析構函數更改爲:

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

這樣內核之前,你的可用內存運行完成。

+0

這將仍然是免費的obj.dataOnGPU應在第二內核可呼叫。 – Dirk

+0

好的 - 所以你只有A級的淺拷貝? –

+0

是的,確切地說。我認爲指定沒有複製構造函數表示執行淺拷貝。 – Dirk

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 
} 

感謝保羅的R用間接指向我這個:)