случайные числа и множественные вызовы srand

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

Я заметил, что многие документы рекомендовали вызвать srand только один раз в программе. Например: случайные числа в C , выбранный ответ «Как правило, только один раз вызовите srand () в вашей программе».

Но почему? Почему было бы так плохо делать что-то вроде этого:

 int THIS_THREAD_SEED; int randomness() { ++THIS_THREAD_SEED; int i; for(i=0 i<1000; i++) { unsigned n = rand_r(&THIS_THREAD_SEED) / RAND_MAX; /* do something with n */ } return 0; } int do_something() { int i; for(i=0; i<1000; i++) { randomness(); } } 

Таким образом, семена меняются один раз за вызов функции, а не один раз для каждой программы. Таким образом, независимо от того, сколько streamов работает, ни один из двух streamов не будет иметь одинаковый список случайных чисел … Правильно?

ОБНОВЛЕНИЕ Предположим, что у меня есть либо уникальное семя для каждого streamа, либо мьютекс на глобальном SEED, чтобы предотвратить условия гонки.

давайте разберем этот вопрос на два отдельных.

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

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

srand() сбрасывает stream чисел, который будет генерировать для вас rand() .

Из руководства по srand:

  The srand() function sets its argument as the seed for a new sequence of pseudo-random integers to be returned by rand(). These sequences are repeatable by calling srand() with the same seed value. 

Если вам нужны «лучшие» случайные числа, тогда rand () предоставляет вам возможность изучить другие источники случайности.

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

И если вы хотите использовать rand_r() из нескольких streamов, все streamи должны иметь локальное семя, вы не должны использовать для этого одну глобальную переменную.

Альтернативой rand() может быть Mersenne Twister

Но если вам нужна «реальная» случайность, вам нужно посмотреть аппаратную поддержку.

И ответить:

Таким образом, семена меняются один раз за вызов функции, а не один раз для каждой программы. Таким образом, независимо от того, сколько streamов работает, ни один из двух streamов не будет иметь одинаковый список случайных чисел … Правильно?

Нет, не работает таким образом, вы должны иметь переменную streamа SEED, инициализированную чем-то уникальным для каждого streamа. Вы можете использовать time() для первого семени, а затем использовать эту случайную последовательность для генерации семян для других streamов или прочитать 4-8 байт из /dev/random или /dev/urandom если вы используете * nix.

Надеюсь, что дает некоторое представление о том, что это полночный гул, спокойная ночь <3

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