2013-09-25 1 views
2

내 단순화 된 버전을 고려하십시오. 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 동작을 원합니다. 어떤 제안? 그래서 커널에서는 메모리를하기 전에 완료 될 때까지 실행되는

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

:

답변

1

당신은 당신의 소멸자를 변경할 수 있습니다. 사용자 정의 복사 생성자를 사용

+0

두 번째 커널에서 사용할 수 있어야이 무료 여전히 것이다 obj.dataOnGPU을 요구. – Dirk

+0

OK - A 클래스의 얕은 복사본 만 보유하고 있습니까? –

+0

네, 그렇습니다. 복사 생성자를 지정하지 않으면 얕은 복사본이 수행된다고 가정합니다. – Dirk

2

솔루션이었다 간접적 :) 저를 가리키는 폴 R에

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 
} 

감사