Монте-Карло подметать в Cuda

У меня есть шаг Монте-Карло в Cuda, с которым мне нужна помощь. Я уже написал серийный код, и он работает как положено. Допустим, у меня есть 256 частиц, которые хранятся в

vector< vector<double> > *r;

Каждый i в r имеет (x, y) компонент, оба из которых являются двойными. Здесь r — положение частицы.

Теперь в CUDA я должен назначить этот вектор на хосте и отправить его на устройство. Оказавшись в устройстве, эти частицы должны взаимодействовать друг с другом. Предполагается, что каждая нить запускает очистку Монте-Карло. Как мне распределить память, указатели ссылок / разыменования с помощью cudaMalloc, который функционирует для создания глобальных / общих ресурсов, …— Я просто не могу обернуться вокруг этого.

Вот как выглядит выделение памяти на данный момент:

cudaMalloc((void**)&r, (blocks*threads)*sizeof(double));
CUDAErrorCheck();
kernel <<<blocks, threads>>> (&r, randomnums);
cudaDeviceSynchronize();
CUDAErrorCheck();
cudaMemcpy(r, blocks*threads*sizeof(double), cudaMemcpyDeviceToHost);

Код выше на уровне картошки. Я думаю, я не уверен, что делать — даже концептуально. Моя главная проблема заключается в распределении памяти и передаче информации на устройство и с него. & хост. Вектор r должен быть выделен, скопирован с хоста на устройство, что-то сделать с ним на устройстве и скопировать обратно на хост. Любая помощь / «указатели» будет высоко ценится.

0

Решение

Ваш код «уровня картофеля» демонстрирует общее непонимание CUDA, включая, но не ограничиваясь, управление r данные. Я бы посоветовал вам расширить свои знания о CUDA, воспользовавшись некоторыми доступными образовательными ресурсами, а затем развить понимание хотя бы одного базового кода CUDA, такого как вектор добавить образец. Тогда вы сможете лучше формулировать вопросы и понимать ответы, которые вы получите. Пример:

Это почти никогда не будет иметь смысла:

    cudaMalloc((void**)&r, (blocks*threads)*sizeof(double));
CUDAErrorCheck();
kernel <<<blocks, threads>>> (&r, randomnums);

Вы либо не знаете очень простой концепции, что данные должны быть переданы на устройство (через cudaMemcpy) до того, как он может быть использован ядром графического процессора, или вы не можете быть обеспокоены написанием кода «уровня картошки», который вообще имеет какой-либо смысл — что может означать отсутствие усилий при написании разумного вопроса. Кроме того, независимо от того, что r есть, проходя &r Я не думаю, что ядро ​​cuda никогда не имело бы смысла.

Относительно вашего вопроса о том, как двигаться r назад и вперед:

  1. Первым шагом в решении вашей проблемы будет пересмотр r позиционировать данные как нечто, что легко может быть использовано ядром графического процессора. В общем, vector не так уж полезно для обычного кода CUDA и vector< vector< > > тем более. И если у вас есть плавающие указатели (*r) тем более. Поэтому сгладьте (скопируйте) ваши данные о положении в один или два динамически распределенных 1-D массива double:

    #define N 1000
    ...
    vector< vector<double> > r(N);
    ...
    double *pos_x_h, *pos_y_h, *pos_x_d, *pos_y_d;
    pos_x_h=(double *)malloc(N*sizeof(double));
    pos_y_h=(double *)malloc(N*sizeof(double));
    for (int i = 0; i<N; i++){
    vector<double> temp = r[i];
    pos_x_h[i] = temp[0];
    pos_y_h[i] = temp[1];}
    
  2. Теперь вы можете выделить место для данных на устройстве и скопировать данные на устройство:

    cudaMalloc(&pos_x_d, N*sizeof(double));
    cudaMalloc(&pos_y_d, N*sizeof(double));
    cudaMemcpy(pos_x_d, pos_x_h, N*sizeof(double), cudaMemcpyHostToDevice);
    cudaMemcpy(pos_y_d, pos_y_h, N*sizeof(double), cudaMemcpyHostToDevice);
    
  3. Теперь вы можете правильно передать данные о местоположении в ваше ядро:

    kernel<<<blocks, threads>>>(pos_x_d, pos_y_d, ...);
    
  4. Копирование данных обратно после того, как ядро ​​будет примерно
    обратный шаг вышеупомянутых шагов. Это поможет вам начать:

    cudaMemcpy(pos_x_h, pos_x_d, N*sizeof(double), cudaMemcpyDeviceToHost);
    cudaMemcpy(pos_y_h, pos_y_d, N*sizeof(double), cudaMemcpyDeviceToHost);
    

Есть много способов снять шкуру с кошки, конечно же, приведенное выше является лишь примером. Однако приведенная выше организация данных будет хорошо подходить для стратегии ядра / потока, которая назначает один поток для обработки одного (x,y) пара позиций.

2

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

Других решений пока нет …

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