2015-01-23 1 views
2

CUDA5.0의 호스트에서 디바이스로 복사하는 것이 더 편리하도록하고 싶습니다. 그래서 함수 인수로 호스트 벡터를 복용 등과 같은 구조를 반환를 만들고 싶었 :구조체의 포인터에 cudaMalloc을 사용하는 방법은 무엇입니까?

template <typename T> 
struct devArr 
{ 
    unsigned int size; //array size 
    T *address;   //address on device 
}; 
의도는 모든 장치에 그 구조를 어디서나 코드 및 만에 장치에 데이터를 복사 전달하는 것입니다

함수는 데이터를 사용하므로 별도로 배열 경계를 처리 할 필요가 없습니다.

예를 들어 그렇게 볼 수있는 구조를 반환하는 기능 :

template <typename T> 
struct cudaArr<T> VectorToDevice(vector<T> arr) 
{ 
    struct devArr<T> darr; 
    darr.size = arr.size(); 
    cudaMalloc((void**)&darr.address, arr.size()*sizeof(T)); 
    cudaMemcpy(darr.address,&arr[0], arr.size()*sizeof(T), cudaMemcpyHostToDevice); 
    return darr; 
} 

그래서 모든 것이 잘 컴파일합니다. 하지만이 코드는 내 구조체의 포인터가 올바른 주소를 가리 키지 않습니다. 구조체에서 포인터를 처리하는 방법의 문제가되어야합니다. 그렇다면 struct에서 포인터로 cudaMalloc을 올바르게 사용하려면 어떻게해야합니까?

감사합니다.

답변

1

정확히 그렇게하는 방법입니다. 저를 혼란스럽게 여기는 것은 포인터가 장치 메모리에 주소를 포함하므로 장치 기능에서만 유효하다는 것입니다. 호스트 코드에서 잘못된 데이터를 가리 킵니다.

+0

마지막 문장 "호스트 코드에서 잘못된 데이터를 가리 킵니다."에서 포인터가 가리키는 데이터를 호스트 코드에서 사용하려고합니까? 이것은 물론 실패하지만, 디바이스에 주소를 보유하고있는 호스트 코드에 포인터를 갖는 것은 완전히 좋습니다. – shaoyl85

+0

예, 저는 커널 기능 외부에서 장치의 데이터를 읽을 수 있다고 생각했습니다. 컴파일러는 그 자체로 주소가 장치에 있음을 알 수 있습니다. 그래서 내 기능을 잘못 알고 있다고 잘못 생각하고 있지만 잘 작동합니다. 그러나 추력 라이브러리는 여기에서 물건을 단순화하는 데 정말 유용합니다. – Daniel

1

외모가 Thrust 인 경우 유용 할 수 있으므로 유스 케이스가 맞으면 좋습니다.

귀하의 코드는 VectorToDevice의 반환 유형이 devArr이어야한다는 점을 제외하고는 cuda api를 올바르게 사용합니다.

다음과 같이하려면 devArr 구조체 전체를 특정 커널 기능에 전달해야합니다. 그런 다음 장치 포인터를 사용할 수 있습니다.

의도는 데이터를 코드의 아무 곳이나 장치로 복사 한 다음 배열 경계를 별도로 처리하지 않고 데이터를 사용하는 모든 장치 기능에만 해당 구조를 전달하는 것입니다.

예를 들어, 다음과 같은 커널 함수를 작성할 수 있습니다

devArr x = VectorToDevice(x_host); 
// prepare y and z similarly. 
add<<<1, 100, 0>>>(x, y, z); 

하지만 당신은 어떤 X를 사용할 수 없습니다,

__global__ void add(devArr x, devArr y, devArr z) { 
    if (threadIdx.x < x.size) { 
    z.address[threadIdx.x] = x.address[threadIdx.x] + y.address[threadIdx.x] 
    } 
} 

그런 다음 당신은 당신의 호스트 코드에서 호출 할 수있는 말 .address는 호스트 코드에서 직접 가리 킵니다.

관련 문제