繰り返し乱数の生成を防ぐ方法は?

繰り返し乱数の生成を防ぐ方法は?

長い話を短く:

プログラムが同時に2回開始されると、同じランダムシードが抽選されます。どうやってこれが起こったのですか?

詳細

MCMC統計分析を実行しているため、プログラム(phylobayes)を2回実行して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);
    ...
}

はい。ソフトウェアの2つのインスタンスが同じマイクロ秒(または正確に1秒の差など)内で機能を実行している場合は、同じシードが得られます。インスタンスをすぐに起動するので、これは意味があります。

これは、gettimeofday()の粒度が通常1μsよりも粗いため、時間的に互いに非常に近い実行がまったく同じマイクロ秒で発生しなくても、同じtv_usec値を持つ可能性があるという事実によってさらに悪化します。

この問題を解決する最善の方法は、ソフトウェアの使用方法に合った異なるシード初期化アルゴリズムを使用して独自のバージョンを構築することです。たとえば、後続の実行ごとにシード数を1ずつ増やしたり、マイクロ秒を使用する代わりに/ dev / randomを使用できます。

または、GNU coreutilsがある場合は、このsleep 0.001コマンドを使用して1ミリ秒間2回目の実行を一時停止できます。これにより、異なるインスタンスが異なるシードを持つのに十分な遅延時間が発生します。

おすすめ記事