Как правильно использовать глобальную память в CUDA?

Я пытаюсь сделать приложение в CUDA, которое использует глобальную память, определенную с устройство.
Эти переменные объявлены в файле .cuh.

В другом файле .cu мой основной, в котором я делаю cudaMallocs и cudaMemCpy.

Это часть моего кода:

cudaMalloc((void**)&varOne,*tam_varOne * sizeof(cuComplex));
cudaMemcpy(varOne,C_varOne,*tam_varOne * sizeof(cuComplex),cudaMemcpyHostToDevice);

varOne объявлен в файле .cuh следующим образом:

    __device__ cuComplex *varOne;

Когда я запускаю свое ядро ​​(я не передаю varOne в качестве параметра) и пытаюсь прочитать varOne с помощью отладчика, он говорит, что не может прочитать переменную. Указатель обращается к нему 000..0, так что очевидно, что это неправильно.

Итак, как мне объявить и скопировать глобальную память в CUDA?

1

Решение

Вы должны сначала определить указатели, которые будут содержать данные, которые будут скопированы в CUDA:
В приведенном выше примере мы, что скопировать массив original_cpu_array к CUDA глобальной памяти.

int original_cpu_array[array_size];
int *array_cuda;

рассчитать размер, который будут занимать данные.

int size = array_size * sizeof(int);

Распределение памяти Cuda:

msg_erro[0] = cudaMalloc((void **)&array_cuda,size);

Копирование с CPU на GPU:

msg_erro[0] = cudaMemcpy(array_cuda, original_cpu_array,size,cudaMemcpyHostToDevice);

Выполнить ядро

Копирование из GPU в CPU:

msg_erro[0] = cudaMemcpy(original_cpu_array,array_cuda,size,cudaMemcpyDeviceToHost);

Свободная память:

cudaFree(array_cuda);

Для отладки я обычно сохраняю состояние функций в массиве (cudaError_t msg_erro [var];). Однако это не является строго необходимым, но сэкономит ваше время, если во время выделения или передачи памяти произойдет ошибка.

И если произошли ошибки, я печатаю, используя что-то вроде:

void printErros(cudaError_t *erros,int size, int flag)
{
for(int i = 0; i < size; i++)
if(erros[i] != 0)
{
if(flag == 0) printf("Alocacao de memoria");
if(flag == 1) printf("CPU -> GPU  ");
if(flag == 2) printf("GPU -> CPU  ");
printf("{%d} => %s\n",i ,cudaGetErrorString(erros[i]));
}
}

Флаг в первую очередь указывает на ту часть кода, в которой произошла ошибка. Например, после выделения памяти:

msg_erro[0] = cudaMalloc((void **)&array_cuda,size);
printErros(msg_erro,msg_erro_size, 0);
2

Другие решения

Я экспериментировал с некоторым примером и обнаружил, что нельзя напрямую использовать глобальную переменную в ядре, не переходя к ней. Даже если вы инициализируете в файле .cuh, вам нужно инициализировать в main ().

Причина:

  1. Если вы объявляете это глобально, память не выделяется в глобальной памяти графического процессора. Вам нужно использовать cudaMalloc((void**)&varOne,sizeof(cuComplex)) для выделения памяти. Он может только распределять память на GPU. Декларация __device__ cuComplex *varOne; работает так же, как объявление прототипа и переменной. Но память не выделяется до cudaMalloc((void**)&varOne,sizeof(cuComplex)) используется.
  2. Также вам нужно инициализировать *varOne в main () в качестве указателя на хост изначально. После использования cudaMalloc(), он узнает, что указатель — это Device Pointer.

Последовательность шагов: (для моего проверенного кода)

int *Ad;        //If you can allocate this in .cuh file, you dont need the shown code in main()

__global__ void Kernel(int *Ad){
....
}

int main(){
....
int size=100*sizeof(int);
cudaMalloc((void**)&Ad,size);
cudaMemcpy(Ad,A,size,cudaMemcpyHostToDevice);
....
}
0

По вопросам рекламы [email protected]