Нужно ли вызывать функцию C srand() для каждого потока или процесса для заполнения рандомизатора?

Надпись в значительной степени говорит об этом.

PS. Это для программы C++ Windows.


person ahmd0    schedule 15.04.2012    source источник
comment
пожалуйста, покажи свой код...   -  person Mitch Wheat    schedule 15.04.2012


Ответы (4)


Согласно документации MSDN на srand() (при условии, что вы используете среду выполнения Microsoft C библиотека), начальное значение является локальным для потока, поэтому вам нужно вызывать srand() для каждого потока, использующего rand(). Обратите внимание, что это может быть не так в других реализациях.

Цитата из MSDN:

Функция srand устанавливает начальную точку для генерации серии псевдослучайных целых чисел в текущем потоке.

person dreamlax    schedule 15.04.2012
comment
Я считаю, что это нестандарт. - person Nawaz; 15.04.2012
comment
@Nawaz: это нестандартно, POSIX не требует, чтобы srand() или rand() были потокобезопасными. - person dreamlax; 15.04.2012
comment
Спасибо. Я пропустил его. Итак, да, кажется, что каждый поток должен сначала заполнить его... какая проблема. - person ahmd0; 15.04.2012
comment
Суть rand() в том, что он генерирует фиксированную последовательность, начиная с начального числа. Трудно понять, насколько это полезно, когда вызовы из других потоков могут изменить последовательность, которую получает вызывающий поток. (Конечно, это справедливый аргумент, что даже если это исправление, это наземная мина, поскольку функция имеет то же имя, но другую семантику.) - person David Schwartz; 15.04.2012

Даже если бы ответ не был специфичен для платформы, я бы посоветовал вам избегать srand() и вместо этого использовать <random>. Библиотека C++11 <random> не только обеспечивает четкую семантику в многопоточных программах, но и предоставляет гораздо лучшие возможности для генерации случайных чисел. Он предоставляет несколько различных генераторов случайных чисел для удовлетворения различных требований к качеству, скорости и размеру, а также множество стандартных дистрибутивов, поэтому вы не совершите ошибок, которые часто делают люди при использовании rand.

person bames53    schedule 15.04.2012
comment
Могу ли я использовать его в программе MS VS 2008 C++, написанной с использованием MFC? - person ahmd0; 15.04.2012
comment
Я думаю, что это было добавлено в VS2010, но конфликта с MFC @ahmd0 нет. - person bames53; 15.04.2012

Нет, согласно Стандарту, потому что когда вы вызываете srand(), это влияет на rand() вызовов из всех потоков.

Функция библиотеки C srand() является однопоточной, как и все другие функции, а это означает, что если вы вызываете srand() из одного потока, она влияет на числовую последовательность, сгенерированную из rand(), и в других потоках.

Но Microsoft предоставляет нестандартный srand(), который действительно требует, чтобы вы вызывали его из всех потоков.

person Nawaz    schedule 15.04.2012
comment
Что ж, технически это тоже правильный ответ, хотя вы должны были сказать «Да» в своем вступительном заявлении, то есть да, вызывать его для каждого потока, верно )) - person ahmd0; 15.04.2012
comment
@ ahmd0: Согласно стандарту, это должно быть No. - person Nawaz; 15.04.2012
comment
Единственные стандарты, которые Microsoft нарушает, — это стандарт потоковой передачи POSIX и стандарты C++11, ни один из которых Microsoft не заявляет о соответствии. Функция Microsoft не является нестандартной, она соответствует стандарту многопоточности Windows, который во многом отличается от стандарта POSIX. Это только один из них. (И Microsoft поняла это правильно, POSIX/ISO ошиблись. См. мой комментарий выше.) - person David Schwartz; 15.04.2012
comment
@DavidSchwartz Microsoft заявляет о поддержке С++ 11. В частности, я слышал, как Херб Саттер сказал, что у них есть полная поддержка стандартной библиотеки C++11. (конечно, я знаю несколько способов, которые неверны в других областях из-за отсутствия языковой функции) - person bames53; 15.04.2012
comment
@ bames53 Мои источники только говорят, что они добавляют много функций C ++ 11 и работают над обеспечением соответствия C ++ 11. Всего два месяца назад они разослали разработчикам опрос с просьбой определить приоритеты функций C++11, чтобы помочь им решить, что добавить. Интересно, будет ли версия, заявляющая о соответствии С++ 11, иметь «фиксированный» srand. (Я не уверен на 100%, что это необходимо для соответствия С++ 11, но я верю, что это так.) - person David Schwartz; 15.04.2012
comment
@DavidSchwartz, похоже, это все равно не требуется для С++ 11. Спецификация упоминает srand только один раз, перечисляя его существование. - person bames53; 15.04.2012
comment
@DavidSchwartz: я согласен с вами, наличие семени как локального для потока имеет больше смысла, и мне кажется странным, что даже в C11 srand() и rand() не требуются, чтобы избежать гонок данных, несмотря на то, что язык теперь имеет стандартизированную поддержку потоков. - person dreamlax; 15.04.2012

Имейте в виду, что состояние является локальным для волокна (более детализированным, чем локальное для потока). Таким образом, для каждого волокна необходимо вызывать srand. (Конечно, если вы не используете волокна, это эквивалентно локальному потоку.)

person tobias.loew    schedule 11.06.2018