Параллельное генерирование случайных чисел - PullRequest
5 голосов
/ 20 ноября 2010

Я пишу параллельную программу, используя open mp, в которой я генерирую матрицу случайных чисел с плавающей запятой, а затем выполняю ряд вычислений на ней.В настоящее время я хочу сделать шаг, на котором я генерирую матрицу, параллельно, но у меня проблема в том, что функция rand () не должна была выполняться одновременно.Я не хочу использовать блокировки для предоставления мьютекса в rand, потому что это единственное, что делается в цикле, и, вероятно, было бы более эффективно запускать его последовательно.Есть ли способ сделать этот шаг эффективно параллельно?

Здесь, если текущий код для этой части (без мьютекса в rand);

#pragma omp parallel default(private)
{
    int i= omp_get_thread_num();
    for(int j=0; j<cols; j++)
        matrix[i][j]= rand()%1000 + (float)(rand()%100)/(float)(rand()%1000);
}

Ответы [ 4 ]

3 голосов
/ 20 ноября 2010

Если вы используете C ++, вам следует рассмотреть возможность использования Boost библиотеки классов случайных чисел .Вы можете создать уникальный экземпляр PRNG для каждого потока.Если вам требуется повторяемость, вы можете инициализировать каждый экземпляр в основном потоке с помощью сгенерированных повторяющихся значений начальных значений.

2 голосов
/ 20 ноября 2010

Я думаю, что вы ищете rand_r (), который явно принимает текущее состояние RNG в качестве параметра.Тогда каждый поток должен иметь свою собственную копию начальных данных (хотите ли вы, чтобы каждый поток начинался с одного и того же начального или другого, зависит от того, что вы делаете, здесь вы хотите, чтобы они были разными, или вы получите ту же строкуопять и опять).Здесь обсуждается rand_r () и потокобезопасность: является ли rand_r реальным потокобезопасным? .

Итак, вы хотите, чтобы каждый поток начинал с начального числа с номера потокачто, вероятно, не то, что вам нужно, поскольку он будет давать одну и ту же матрицу каждый раз, когда вы запускаете с одинаковым количеством потоков, но просто в качестве примера):

#pragma omp parallel default(none) shared(matrix, cols)
{
    int i= omp_get_thread_num();
    unsigned int myseed = i;
    for(int j=0; j<cols; j++)
        matrix[i][j]= rand_r(&myseed)%1000 + (float)(rand_r(&myseed)%100)/(float)(rand_r(&myseed)%1000 + 1);
}

Теперь каждый поток изменяет свое собственное состояниеисключительно (rand_r () - чистая функция) и вы должны быть дома свободны.

0 голосов
/ 20 ноября 2010

Настоящая проблема в том, что если вам нужна воспроизводимость, что часто требуется при тестировании.С заданным семенем генерируют последовательность нитей семян.Тогда каждый поток будет использовать свое собственное начальное число для генерации чисел.

Тот факт, что rand() не является потокобезопасным, вряд ли является проблемой.Существует множество доступных алгоритмов и тривиально накатить один экземпляр (состояние) на поток, например, просто начать с http://en.wikipedia.org/wiki/Random_number_generation#Computational_methods.Блокировка для каждого rand() вызова была бы катастрофой параллелизма.

0 голосов
/ 20 ноября 2010

Если псевдослучайный достаточно хорош (см. Комментарий Бена), то вы можете создать свой собственный PRNG (например, Twister Mersenne, а не метод слабого модуля по модулю, используемый большинством систем) и реализовать один независимый генератор на поток. если вы сделаете это, вы ДОЛЖНЫ убедиться, что каждый генератор имеет разные начальные значения.

...