반복되는 난수 생성을 방지하는 방법은 무엇입니까?

반복되는 난수 생성을 방지하는 방법은 무엇입니까?

긴 이야기 짧게:

프로그램이 동시에 두 번 시작되면 동일한 무작위 시드가 추첨됩니다. 어떻게이 일이 일어 났어요?

세부 사항

MCMC 통계 분석을 실행 중이므로 프로그램(phylobayes)을 두 번 실행하여2 독립복사.

이를 위해 내 쉘 스크립트는 각 복사 실행을 다음과 같이 (도식적으로) 분리합니다.

pb -d "inputdata" "replicate1" &
pid1=$!

pb -d "inputdata" "replicate2" &
pid2=$!

wait "$pid1"
wait "$pid2"

(그런 다음 slurm을 사용하여 이 스크립트를 컴퓨팅 클러스터(Debian 10)에 제출합니다 sbatch.)

하지만 내 실행의 대부분(예: 30%)은 동일한 무작위 시드에서 시작됩니다! 로그 파일에 표시된 대로입니다.

필로베이C++ Random::initRandom()명령을 사용합니다. [편집하다:실제로 지적한 대로 이 함수에는 패키지 내부에 사용자 정의 정의가 있습니다.]

동일한 무작위 시드를 사용하는 것이 기술적으로 가능합니까?/dev/random 또는 /dev/urandom을 사용합니까?

그렇다면 sleep시작 사이에 명령을 삽입하겠습니다.

그렇지 않다면 내가 무슨 어리석은 실수를 했는지 이해해야 하는데, 그게 무슨 일인지는 모르겠습니다...

답변1

동일한 무작위 시드를 사용하는 것이 기술적으로 가능합니까?

연결된 함수를 보면 마이크로초를 시드로 사용하는 것을 볼 수 있습니다(모듈로 10^6).

void Random::InitRandom(int seed)   {

    if (seed == -1) {
        struct timeval tod;
        gettimeofday(&tod, NULL);
        seed = tod.tv_usec; // <== this line
    }
    Seed = seed;
    srand(seed);
    ...
}

그렇습니다. 소프트웨어의 두 인스턴스가 동일한 마이크로초(또는 정확히 1초의 차이 등) 내에 기능을 실행하는 경우 동일한 시드를 얻게 됩니다. 인스턴스를 즉시 시작하므로 이는 의미가 있습니다.

이는 gettimeofday()의 세분성이 일반적으로 1μs보다 더 거칠기 때문에 시간상 서로 매우 가까운 실행이 정확히 동일한 마이크로초에 발생하지 않더라도 동일한 tv_usec 값을 가질 수 있다는 사실로 인해 더욱 악화됩니다.

이 문제를 해결하는 가장 좋은 방법은 소프트웨어 사용 방식에 맞는 다른 시드 초기화 알고리즘을 사용하여 자신만의 버전을 구축하는 것이라고 생각합니다. 예를 들어, 후속 실행마다 시드 수를 1씩 늘리거나 마이크로초를 사용하는 대신 /dev/random을 사용할 수 있습니다.

또는 GNU coreutils가 있는 경우 이 sleep 0.001명령을 사용하여 1밀리초 동안 두 번째 실행을 일시 중지할 수 있습니다. 이렇게 하면 서로 다른 인스턴스가 서로 다른 시드를 가질 수 있을 만큼 충분한 지연 시간이 발생합니다.

관련 정보