2016-12-05 4 views
0

Следующий простой сценарий произвести случайное число в параллельномпоточно-генератор случайных чисел с OpenMP

#include <random> 
#include <iostream> 
#include <omp.h> 

int main(int argc, char *argv[]) 
{ 
    // Three integers are expected from the command line. 
    // The first integer is a random seed 
    // The second integer is the number of threads. 
    // The third integer indicates the number of random numbers to produce 

    // Read the seed and create the random number generator and the random distribution 
    int seed = std::stoi(argv[1]); 
    std::mt19937 mt(seed); 
    std::uniform_real_distribution<float> dist(0, 100); 

    // Read the number of threads and set it. 
    int nbThreads = std::stoi(argv[2]); 
    omp_set_num_threads(nbThreads); 

    // Number of random number for demonstration 
    int n = std::stoi(argv[3]); 

    // Will store the random number to print them conveniently 
    std::vector<float> store(n); 

    // produce 'n' random numbers 
    #pragma omp parallel for 
    for (int i = 0 ; i < n ; ++i) 
    { 
    store[i] = dist(mt); 
    } 

    // print the random numbers 
    for (auto& rnd : store) 
    { 
    std::cout << rnd << std::endl; 
    } 

    return 0; 
} 

Приведенный выше скрипт детерминированным при использовании одного потока

./test 3 1 2 
55.0798 
7.07249 

./test 3 1 2 
55.0798 
7.07249 

./test 7 1 2 
7.63083 
22.7339 


./test 7 1 2 
7.63083 
22.7339 

Однако, это частично стохастическим и содержать корреляцию между потоками (что может быть довольно большой проблемой) при использовании более одной нити

./test 3 2 2 
43.1925 
43.1925 

./test 3 2 2 
55.0798 
7.07249 

./test 7 2 2 
22.7339 
7.63083 

./test 7 2 2 
7.63083 
7.63083 

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

Цель состоит в том, что ./test 87 1 200 дают тот же результат, как ./test 87 3 200 (то есть число потоков не будет влиять на объект store). Если это невозможно, то целью является то, что ./test 87 3 200 дает тот же результат, что и ./test 87 3 200.

+0

Можете ли вы уточнить, что вы хотите сделать? Очевидно, что PRNG, который производит последовательность выходов, может воспроизводить только эти выходы последовательно. Что ты хочешь? –

+0

@DavidSchwartz Я редактировал сообщение, надеясь сделать его более понятным. Я пытаюсь сделать детерминированный процесс, который принимает случайное семя и производит случайное число многопоточным способом. Является ли это возможным? Я не уверен, что мой комментарий просто помог вам понять. Не могли бы вы уточнить, что неясно? –

+0

Каковы темы, которые будут делать именно? Чтобы результат был детерминированным, должен быть первый результат, который идет в какое-то конкретное место. И тогда, и только тогда, может быть второй результат. Правильно? Кажется, вы просите, чтобы они делали вещи в определенной последовательности (один, затем следующий и т. Д.), Но также делали их многопоточно. –

ответ

1

Вы делите состояние в объекте std::mt19937 mt с каждым потоком, который не является потокобезопасным.

Либо оберните доступ к этому объекту с помощью какой-либо блокировки, либо предоставите отдельный экземпляр для каждого потока [ИЗМЕНИТЬ], засеянного по-другому (возможно, из первого экземпляра mt19937, который вы создаете), чтобы каждый экземпляр выдавал разные результаты [/ EDIT] (если это возможно, используя omp).

+0

Спасибо за ваш ответ. Блокировка возможна с помощью openMP (как можно прочитать [здесь] (http://bisqwit.iki.fi/story/howto/openmp/#Locks)), но я действительно не понимаю, что это значит. Кроме того, можете ли вы уточнить, когда вы говорите «предоставить отдельный экземпляр»?Если я просто скопирую «mt», то каждый поток будет выдавать точный результат. Это будет отличаться от того, что будет производить один поток, и это вызовет повторные значения в 'store', что нежелательно. Не могли бы вы немного расширить? –

+0

См. Редактирование. Я знаком с threading, просто не openMP. –

-1

Предоставление двух разных экземпляров mt19937 (по одному для каждого потока, засеянного по-разному) - не лучший способ сделать это. Существует библиотека, предназначенная для RNG в поточной среде, которую вы можете найти here. Убедитесь, что вы прочитали документацию, это очень хорошо написано, см. Раздел 2.2.

+0

Не могли бы вы обобщить ** почему ** поточно-локальные экземпляры RNG - это не лучший способ сделать это, как сделать это лучше концептуальным? Ссылка на библиотеку отличная, и я уверен, что это документация, но важно иметь это также в ответе. – Zulan