Генератор случайных чисел в CUDA - PullRequest
14 голосов
/ 08 мая 2009

Я боролся с этим весь день, я пытаюсь получить генератор случайных чисел для потоков в моем коде CUDA. Я просмотрел все форумы, и да, эта тема встречается довольно часто, но я часами пытался разгадать все виды кодов, но безрезультатно. Если кто-нибудь знает простой метод, возможно, ядро ​​ device , которое можно вызвать для возврата случайного числа с плавающей точкой от 0 до 1, или целое число, которое я могу преобразовать, я был бы очень признателен.

Опять же, я надеюсь использовать случайное число в ядре, например, как rand ().

Заранее спасибо

Ответы [ 8 ]

11 голосов
/ 11 апреля 2012

Для всех, кто заинтересован, теперь вы можете сделать это через cuRAND .

5 голосов
/ 08 мая 2009

Я не уверен, что понимаю, зачем тебе нужно что-то особенное. Любой традиционный PRNG должен портировать более или менее напрямую. линейная конгруэнтная должна работать нормально. У вас есть какие-то особые свойства, которые вы пытаетесь установить?

4 голосов
/ 15 июля 2013

Я думаю, что любое обсуждение этого вопроса должно отвечать на оригинальный запрос Зенны, и это для уровня потока реализации. В частности, функция устройства , которая может быть вызвана из ядра или потока . Извините, если я переборщил с "жирными" фразами, но я действительно думаю, что ответы пока не совсем касаются того, что здесь ищут.

Библиотека cuRAND - ваш лучший выбор. Я ценю, что люди хотят заново изобрести колесо (это позволяет оценить и более правильно использовать сторонние библиотеки), но высокопроизводительные высококачественные генераторы чисел многочисленны и хорошо протестированы. Лучшая информация, которую я могу порекомендовать, находится в документации по библиотеке GSL для различных генераторов здесь: http://www.gnu.org/software/gsl/manual/html_node/Random-number-generator-algorithms.html

Для любого серьезного кода лучше всего использовать один из основных алгоритмов, которые математики / компьютерные ученые используют для поиска системных недостатков. «Mersenne Twister» - это нечто с периодом (повторяющийся цикл) порядка 10 ^ 6000 (алгоритм MT19997 означает «Mersenne Twister 2 ^ 19997»), которое было специально адаптировано для использования Nvidia на уровне потоков в потоках та же самая деформация, используя вызовы идентификатора потока как семена. См. Статью здесь: http://developer.download.nvidia.com/compute/cuda/2_2/sdk/website/projects/MersenneTwister/doc/MersenneTwister.pdf. На самом деле я работаю над реализацией чего-либо, используя эту библиотеку, и, если я получу ее для правильной работы, я опубликую свой код. У Nvidia на сайте документации есть несколько примеров текущего инструментария CUDA.

ПРИМЕЧАНИЕ: Просто для записи, я не работаю на Nvidia, но я признаю, что их документация и дизайн абстракций для CUDA меня очень впечатлили.


4 голосов
/ 20 ноября 2009

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

Примером чехарды может быть:

template <typename ValueType>
__device__ void leapfrog(unsigned long &a, unsigned long &c, int leap)
{
    unsigned long an = a;
    for (int i = 1 ; i < leap ; i++)
        an *= a;
    c = c * ((an - 1) / (a - 1));
    a = an;
}

template <typename ValueType>
__device__ ValueType quickrand(unsigned long &seed, const unsigned long a, const unsigned long c)
{
    seed = seed * a;
    return seed;
}

template <typename ValueType>
__global__ void mykernel(
    unsigned long *d_seeds)
{
    // RNG parameters
    unsigned long a = 1664525L;
    unsigned long c = 1013904223L;
    unsigned long ainit = a;
    unsigned long cinit = c;
    unsigned long seed;

    // Generate local seed
    seed = d_seeds[bid];
    leapfrog<ValueType>(ainit, cinit, tid);
    quickrand<ValueType>(seed, ainit, cinit);
    leapfrog<ValueType>(a, c, blockDim.x);

    ...
}

Но тогда период этого генератора, вероятно, будет недостаточным в большинстве случаев.

Если честно, я бы посмотрел на использование сторонней библиотеки, такой как NAG . В SDK также есть несколько генераторов пакетов, но в данном случае это, вероятно, не то, что вам нужно.

EDIT

Поскольку за это только что проголосовали, я думаю, что стоит обновить, чтобы упомянуть, что cuRAND , как уже упоминалось в более поздних ответах на этот вопрос, доступно и предоставляет ряд генераторов и дистрибутивов. Это определенно самое легкое место для начала.

3 голосов
/ 01 сентября 2012

Лучшим способом для этого является написание собственной функции устройства , вот такая

void RNG()
{   
    unsigned int m_w = 150;
    unsigned int m_z = 40;

    for(int i=0; i < 100; i++)
    {
        m_z = 36969 * (m_z & 65535) + (m_z >> 16);
        m_w = 18000 * (m_w & 65535) + (m_w >> 16);

        cout <<(m_z << 16) + m_w << endl;  /* 32-bit result */
    }
}

Это даст вам 100 случайных чисел с 32-битным результатом.

Если вам нужны случайные числа от 1 до 1000, вы также можете взять result%1000, либо в точке потребления, либо в точке генерации:

((m_z << 16) + m_w)%1000

Изменение начальных значений m_w и m_z (в примере 150 и 40) позволяет вам каждый раз получать разные результаты. Вы можете использовать threadIdx.x в качестве одного из них, который каждый раз должен давать разные псевдослучайные ряды.

Я хотел бы добавить, что он работает в 2 раза быстрее функции rand () и отлично работает;)

2 голосов
/ 16 июня 2009

Я не нашел хорошего генератора параллельных чисел для CUDA, однако я нашел параллельный генератор случайных чисел на основе академических исследований здесь:

2 голосов
/ 08 мая 2009

Существует пакет MDGPU (GPL), который включает в себя реализацию функции GNU rand48 () для CUDA здесь .

Я нашел это (довольно легко, используя Google, который, я полагаю, вы пробовали :-) на форумах NVidia здесь .

0 голосов
/ 16 июля 2014

Вы можете попробовать Mersenne Twister для графических процессоров

Он основан на SIMD-ориентированном Fast Mersenne Twister (SFMT), который является довольно быстрым и надежным генератором случайных чисел. Он проходит тесты Marsaglias DIEHARD для генераторов случайных чисел.

...