Почему rand () не такой случайный после fork? - PullRequest
10 голосов
/ 24 декабря 2011
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    int i =10;
    /* initialize random seed:  */
    srand(time(NULL));
    while(i--){
        if(fork()==0){
            /* initialize random seed here does not make a difference:
            srand(time(NULL));
             */
            printf("%d : %d\n",i,rand());
            return;
        }
    }
    return (EXIT_SUCCESS);
}

Печатает одно и то же (разное при каждом прогоне) 10 раз - ожидается?У меня есть более сложный кусок кода, где каждый разветвленный процесс выполняется по очереди - без разницы

Ответы [ 7 ]

18 голосов
/ 24 декабря 2011

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

srand(time(NULL) ^ (getpid()<<16));
5 голосов
/ 24 декабря 2011

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

5 голосов
/ 24 декабря 2011

Функция rand() является генератором чисел псевдослучайного .Это означает, что последовательность сгенерированных чисел является детерминированной и зависит только от предоставленного начального числа.

Поскольку вы выполняете один и тот же процесс 10 раз, состояние генератора случайных чисел одинаководля каждого ребенка.В следующий раз, когда вы вызовете rand(), вы получите то же самое значение.

Вызывая srand(time(NULL)) внутри дочернего процесса, вы потенциально помогаете, но гранулярность time() только1 секунда, так что все ваши дети, вероятно, начинают в одну и ту же секунду.При заполнении с тем же значением создается та же псевдослучайная последовательность.

Вы можете попробовать заполнить со значением, которое зависит от номера ребенка:

srand(time(NULL) - i*2);

(я использовал i*2 всобытие, которое time() продвигается на 1 секунду во время цикла разветвления.)

2 голосов
/ 24 декабря 2011

Причина, по которой даже добавление srand(time(NULL)); (строка внутри блока if, которую вы прокомментировали) внутри цикла, не имеет значения, потому что современные компьютеры могут выполнять весь этот блок очень быстро, а timeсчитает в секундах.Из справочных страниц:

time () возвращает время в виде количества секунд с начала эпохи ...

Если добавить sleep(1); после if в цикле while и раскомментирование вызова srand результаты будут другими, поскольку time теперь будет возвращать другое значение, поскольку истекла секунда.

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

0 голосов
/ 02 декабря 2014

Это решит проблему:

srand48((long int)time(NULL));
i= (lrand48()/rand()+1) % 123

Я не проверял с помощью fork, но внутри для вызова 100 раз он работает.

семя с номером пид. Это немного, но трудно решить проблему.

Это было на какой-то странице: «это сработало srand (time (0) + getpid ()); но я должен был вызвать это в случае 0, т.е. дочерний процесс».

0 голосов
/ 24 декабря 2011

Вы не пересеваете, когда делаете дочерний процесс. Состояние генератора случайных чисел точно такое же.

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

Попробуйте посеять что-то другое и более случайное.

0 голосов
/ 24 декабря 2011

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

...