2016-12-14 1 views
1

나는 cuda, 특히 통합 메모리 (내 마지막 실제 cuda dev는 3 년 전이었습니다)로 내 마음을 상쾌합니다. 나는 녹슬 었습니다.cuda 통합 메모리 및 포인터 앨리어싱

PB에 :

내가 하나로 통합 메모리를 사용하여 컨테이너에서 작업을 만드는 오전. 그러나 수 일간 조사한 후 충돌이 발생합니다. 어디에서 충돌 (복사 생성자)이 있는지 말할 수는 없지만 그 이유는 아닙니다. 모든 포인터가 올바르게 할당되기 때문입니다.

나는 엔비디아 포스트 (https://devblogs.nvidia.com/parallelforall/unified-memory-in-cuda-6/) C++에 대한 과 수축하지 오전

#include <cuda.h> 
#include <cstdio> 

template<class T> 
struct container{ 
    container(int size = 1){ cudaMallocManaged(&p,size*sizeof(T));} 
    ~container(){cudaFree(p);} 
    __device__ __host__ T& operator[](int i){ return p[i];} 
    T * p; 
}; 

struct task{ 
    int* a; 
}; 

__global__ void kernel_gpu(task& t, container<task>& v){ 
    printf(" gpu value task %i, should be 2 \n", *(t.a)); // this work 
    task tmp(v[0]); // BUG 
    printf(" gpu value task from vector %i, should be 1 \n", *(tmp.a)); 
} 

void kernel_cpu(task& t, container<task>& v){ 
    printf(" cpu value task %i, should be 2 \n", *(t.a)); // this work 
    task tmp(v[0]); 
    printf(" cpu value task from vector %i, should be 1 \n", *(tmp.a)); 
} 

int main(int argc, const char * argv[]) { 
    int* p1; 
    int* p2; 
    cudaMallocManaged(&p1,sizeof(int)); 
    cudaMallocManaged(&p2,sizeof(int)); 
    *p1 = 1; 
    *p2 = 2; 

    task t1,t2; 
    t1.a=p1; 
    t2.a=p2; 

    container<task> c(2); 

    c[0] = t1; 
    c[1] = t2; 

    //gpu does not work 
    kernel_gpu<<<1,1>>>(c[1],c); 
    cudaDeviceSynchronize(); 

    //cpu should work, no concurent access 
    kernel_cpu(c[1],c); 

    printf("job done !\n"); 

    cudaFree(p1); 
    cudaFree(p2); 

    return 0; 
} 

가 객관적으로 내가 메모리가 제대로 할당 된 인수로 개체를 전달할 수있는 메모리 통합. 그러나 2 차 학위를 사용할 수없는 것처럼 보입니다. 간접 지정의 (여기서 컨테이너)

개념상의 실수를하고 있습니다. 그러나 나는 어디를 보지 못합니다.

보다도,

Timocafe

내 컴퓨터는

: 기억이 통합 메모리로 할당되었지만 7.5, GCC 4.8.2 CUDA, 테슬라 K20 m은

+0

'task' 클래스는 GPU에서 올바르게 작동하도록하는 생성자를 가지고 있지 않습니다. – talonmies

답변

1

, 컨테이너 자체는 호스트 코드에서 선언 호스트 메모리에 할당 됨 : container<task> c(2);. 이를 장치 코드에 대한 참조로 전달할 수 없으며 커널에서이를 참조 해제하면 불법적 인 메모리 액세스가 발생할 가능성이 큽니다.

이러한 문제를 확인하려면 cuda-memcheck을 사용할 수 있습니다.

+0

ok하지만 작업 (첫 번째 인수)에서 왜 작동합니까? 작업 객체가 호스트에 할당되고 cuda를 사용하여 메모리가 외부로 통일됩니다. 최악의 경우 벡터와 연산자를 사용하여 작업을 전달합니다 [] –

+0

'작업 t1'은 [http://en.cppreference.com/w/cpp/concept/TriviallyCopyable] (TriviallyCopyable) 괜찮습니다. 그러나 컨테이너에 사용자 정의 소멸자가있는 것은 아니므로 컨테이너를 TriviallyCopyable이 아닌 [http://en.cppreference.com/w/cpp/language/destructor#Trivial_destructor](Trivial 소멸자)] 요구 사항을 위반합니다. – yhf8377

+0

왜냐하면 (호스트 코드에서 선언되었지만 장치에 할당 된 메모리로 채워진) 포인터를 커널에 전달할 수 있기 때문입니다. – yhf8377