Пример кода ядра со стороны cuRand Mersenne twister __device__

Я работаю над реализацией алгоритма Монте-Карло цепи Маркова (MCMC) на NVIDIA CUDA GPU. Алгоритм CPU MCMC использует высококачественный генератор случайных чисел Mersenne Twister, и я хотел бы использовать его в написанных мною ядрах графического процессора. Я давно искал примеры кода cuRand MT. К сожалению, я никогда не видел примеров кода ядра, использующего Twister Мерсенна. Стандартная документация библиотеки cuRand предоставляет набор функций для MTGP (MT для графического процессора), но неясно, как их использовать.

Примеры CUDA содержат пример MersenneTwisterGP11213.tar.gz , но, похоже, он предназначен исключительно для кода хоста, который запрашивает быстрое создание массива случайных чисел на GPU, загружает их в память CPU и обрабатывает CPU. Существует также статья «Массово параллельный ГСЧ с использованием CUDA C, Thrust и C #» . Опять же, автор в последнем разделе «Реализация Mersenne Twister с использованием CUDA C» предоставляет только упрощенную часть вышеупомянутого кода хоста из «Примеры CUDA».

Итак, мой первый вопрос: может ли кто-нибудь привести мне пример функции global или device, которая использует twister cuRand Mersenne?

У меня есть еще один вопрос. В настоящее время я использую генератор случайных чисел библиотеки cuRand и понятия не имею, какой генератор используется! Позвольте мне представить пару фрагментов моего кода. Это инициализация генератора:

 __global__ void init_rng(Cmcmcfit *mc) {

        int ist = threadIdx.x*gridDim.x + blockIdx.x;

        if (ist >= mc->nrndst) return; // The last block can have extra threads

        unsigned long long offset = 0;

        curand_init(mc->seed, ist, offset, &mc->rndst[ist]);
}

В других ядрах я выбираю числа из равномерного и нормального распределений. Массив состояний всех blockDim.x*gridDim.x генераторов сохраняется в глобальной памяти, массив mc->rndst[]. Например, curand_uniform() используется:

  .   .   .   .   .   .
  do { /* Randomly select parameter number k to make step */
    r = curand_uniform(&mc->rndst[ist]);
    k = (int) (mc->nprm*r); /* Random parameter index 0..nprm-1 into ivar[] */
  } while (k >= mc->nprm);
  .   .   .   .   .   .   .   .   .

Или для выборки из распределения Гаусса используется curand_normal():

  std = mc->pstp[(Nbeta*k + Ibeta)*Nseq + Iseq]; /* pstp[k,ibeta,iseq] */
  randn = curand_normal(&mc->rndst[ist]);
  p = p + std*randn;

Кто-нибудь может сказать мне, какой из генераторов cuRand (xorwow, lcs, mtgp ...) здесь используется (собственно, по умолчанию)?


person Benkevitch    schedule 27.05.2013    source источник


Ответы (1)


curand документация включает раздел об API устройства примеры. Во втором примере MTGP используется для генерации случайных чисел в коде устройства, а затем в том же ядре выполняется базовое вычисление сгенерированных случайных чисел (подсчитайте число, у которого установлен самый низкий бит). Это похоже на то, что вы спрашиваете. for (как сгенерировать случайные числа на устройстве и использовать их в коде устройства). Там чего-то не хватает?

Кроме того, в документации указывает, что генератор по умолчанию, используемый curand это XORWOW:

Генератор псевдослучайных чисел по умолчанию, XORWOW, ...

и также здесь.

person Robert Crovella    schedule 27.05.2013
comment
Роберт, большое спасибо. Похоже, это ТОЧНО то, о чем я просил! - person Benkevitch; 28.05.2013
comment
@Benkevitch: Если ответ Роберта ответил на ваш вопрос (похоже, что это так), пожалуйста, примите его ответ, чтобы вопрос был удален из списка неотвеченных вопросов. - person njuffa; 28.05.2013