2016-01-03 2 views
-2

Я был болен, глядя на весь код шаблонного Cuda для копирования данных на устройство, так что я написал эту функцию обертку:функция обертка для cudaMalloc и cudaMemcpy

void allocateAndCopyToDevice(void* device_array, const void* host_array, const size_t &count) 
{ 
    gpuErrchk(cudaMalloc((void**)&device_array, count)); 
    gpuErrchk(cudaMemcpy(device_array, host_array, count, cudaMemcpyHostToDevice)); 
} 

, но по какой-то причине это привело в из ограничивает доступ к памяти при использовании массива, инициализированного таким образом. Код инициализации, который я использовал, выглядит так:

cuDoubleComplex *d_cmplx; 
allocateAndCopyToDevice(d_cmplx,cmplx,size*sizeof(cuDoubleComplex)); 

Может ли кто-нибудь объяснить, почему это не работает?


После просмотра комментария immibis, я понял, что cudaMalloc ожидает указатель на указатель, так что вместо этого я прохожу по значению указателя на указатель:

void allocateAndCopyToDevice(void** device_array, const void* host_array, const size_t &count) 
{ 
    gpuErrchk(cudaMalloc(device_array, count)); 
    gpuErrchk(cudaMemcpy(*device_array, host_array, count, cudaMemcpyHostToDevice)); 
} 

и инициализация теперь выглядит следующим образом :

cuDoubleComplex *d_cmplx; 
allocateAndCopyToDevice((void **)&d_cmplx,cmplx,size*sizeof(cuDoubleComplex)); 

Это работает, но мне все же интересно, есть ли лучший способ сделать это? Как другие люди обрабатывают передачи памяти в коде cuda?

+4

Подсказка: почему 'недействительным п (INT х) {х = 42;} Int основной() {Int J ; е (к); printf ("% d \ n", j); return 0;} 'not print 42? – immibis

+1

@immibis: Может, потому что 'j' не инициализирован. – Olaf

+0

* Я не передавал указатель по ссылке. * - Вы по-прежнему не передаете указатель по ссылке. Вы по-прежнему передаете значение, но это значение является «void **» вместо (ошибочного) 'void *'. Передача по ссылке в C++ означает именно то, что - передача ссылки (ссылка не указатель). – PaulMcKenzie

ответ

2

Я хотел бы сделать что-то вроде

template <typename T> 
T* allocateAndCopyToDevice(const T* host_array, std::size_t count) 
{ 
    // some static_assert for allowed types: pod and built-in. 
    T* device_array = nullptr; 
    gpuErrchk(cudaMalloc(&device_array, count * sizeof(T))); 
    gpuErrchk(cudaMemcpy(device_array, host_array, count * sizeof(T), cudaMemcpyHostToDevice)); 
    return device_array; 
} 

и использовать его:

cuDoubleComplex *d_cmplx = allocateAndCopyToDevice(cmplx, size); 
+0

это лучше, чем у меня. Почему вам нужно использовать nullptr? – zimzam

+1

Я предпочитаю всегда инициализировать переменные. – Jarod42

Смежные вопросы