Mathematica/CUDA сокращают время выполнения

Я пишу простую симуляцию Монте-Карло для переноса частиц. Мой подход заключается в написании ядра для CUDA и выполнении его как функции Mathematica.

Ядро:

#include "curand_kernel.h"
#include "math.h"

extern "C" __global__ void monteCarlo(Real_t *transmission, mint seed, mint pathN) {
curandState rngState;

int index = threadIdx.x + blockIdx.x*blockDim.x;

curand_init(seed, index, 0, &rngState);

if (index < pathN) {
    //-------------start one packet run----------------------

    float packetWeight = 1.0;
    int m = 0;

    while(packetWeight > 0.0){

        //MONTE CARLO CODE

        // Test: still in the sample?
            if(z_coordinate > sampleThickness){
                packetWeight = 0;
                z_coordinate = sampleThickness;
                transmission[index]=1;
            }
        }
    }
    //-------------end one packet run------------------------
}
}

Математический код:

Needs["CUDALink`"];
cudaBM = CUDAFunctionLoad[code, 
"monteCarlo", {{_Real, "Output"}, _Integer, _Integer}, 256, 
"UnmangleCode" -> False];


pathN = 100000;
result = 0;  (*count for transmitted particles*)
For[j = 0, j < 10, j++,
   buffer = CUDAMemoryAllocate["Float", 100000];
   cudaBM[buffer, 1490, pathN];
   resultOneRun = Total[CUDAMemoryGet[buffer]];
   result = result + resultOneRun;
];

Вроде пока все работает, но прирост скорости по сравнению с чистым кодом на C без CUDA незначителен. У меня две проблемы:

  1. функция curand_init() выполняется всеми потоками в начале каждого шага суммирования -> могу ли я вызвать эту функцию один раз для всех потоков?
  2. ядро возвращает Mathematica очень большой массив вещественных чисел (100 000). Я знаю, что узким местом CUDA является пропускная способность канала между GPU и CPU. Мне нужна только сумма всех элементов списка, поэтому было бы эффективнее вычислить сумму элементов списка в GPU и отправить в CPU только одно вещественное число.

person user1961006    schedule 09.01.2013    source источник
comment
Вы не можете использовать CUDATotal ?   -  person b.gatessucks    schedule 09.01.2013
comment
CUDATotal будет выполняться после того, как массив результатов будет скопирован обратно в память процессора. Я хочу избежать копирования всего массива результатов в память процессора. Я думаю, что решение должно быть в части C кода. Благодарю за ваш ответ.   -  person user1961006    schedule 09.01.2013
comment
Если это так, я совершенно неправильно понял документацию по этому вопросу; Спасибо за ответ.   -  person b.gatessucks    schedule 09.01.2013


Ответы (2)


1) Если вам нужно выполнить curand_init() один раз для всех потоков, можете ли вы просто сделать это в ЦП и передать в качестве аргумента CUDA?

2) Как насчет функции "device float sumTotal", которая суммирует и возвращает ваши значения? Вы скопировали столько же данных *transmission в разделяемый буфер памяти?

person roboto1986    schedule 09.01.2013

Согласно документам CURAND, «Вызовы curand_init() медленнее, чем вызовы curand() или curand_uniform(). Большие смещения для curand_init() занимают больше времени, чем меньшие смещения. Гораздо быстрее сохранить и восстановить состояние генератора случайных чисел, чем повторно вычислить начальное состояние."

http://docs.nvidia.com/cuda/curand/index.html#topic_1_3_4

Также, пожалуйста, загляните в эту тему для получения более подробной информации Программа CUDA вызывает сбой драйвера nvidia

person Ramya Maithreyi    schedule 09.01.2013