7

「奇偶」ソートを実装するために MPICH2 を使用しています。私は実装を行いましたが、各プロセスの値をランダム化すると、同じ数がすべてのプロセスにランダム化されます。

各プロセスのコードは次のとおりです。各プロセスは値をランダム化しています。

int main(int argc,char *argv[])
{
    int  nameLen, numProcs, myID;
    char processorName[MPI_MAX_PROCESSOR_NAME];
    int myValue;

    MPI_Init(&argc,&argv);
    MPI_Comm_rank(MPI_COMM_WORLD,&myID);
    MPI_Comm_size(MPI_COMM_WORLD,&numProcs);    
    MPI_Get_processor_name(processorName,&nameLen);
    MPI_Status status;

    srand((unsigned)time(NULL));
    myValue = rand()%30+1; 

    cout << "myID: " << myID << " value: " << myValue<<endl;
    MPI_Finalize();

    return 0;
 }

各プロセスが同じ値を取得するのはなぜですか?

編集:答えてくれてありがとう:)

ラインを変えました

 srand((unsigned)time(NULL));

 srand((unsigned)time(NULL)+myID*numProcs + nameLen);

そして、プロセスごとに異なる値を与えます:)

4

2 に答える 2

6

このタスクは簡単ではありません。

srand()で初期化するため、同じ数値が得られますtime(0)。現在の秒をtime(0)返します(エポック以降)。したがって、すべてのプロセスが同期されたクロックを持っている場合、同じ秒で呼び出される限り、すべてが同じシードで初期化されますsrand()。これはかなり可能性が高いです。大型マシンでもこれを観察しました。

解決策 1. ローカル値を使用してランダム シードを初期化します。

私がしたことは、ランダム シードの計算に、クロックよりも物理マシンに対してよりローカルな とcat /proc/meminfo組み合わせたメモリ使用量を含めることでした。/dev/randomこれは、1 台のマシンで N 個のタスクを実行すると失敗する可能性があることに注意してください。しかし、私の記憶が正しければ、 も使用していtask_idました。タスクにローカルなものであれば何でも十分です。素材を組み合わせるのもいいですね。結局、この計算は実際の計算に比べて非常に短いはずです。そして、安全な側にとどまる方が良いです。

解決策 2. 前処理ステップとしてシードを計算します。

メソッドを使用してランダムシードを生成task 0し、 で伝播することもできますsend-to-all。ただし、大規模になるとスケーリングの問題が発生する可能性があります (10^5 プロセスなど)。他の方法を使用してパラメーターをロードし、前処理ステップとしてシードを準備することもできます。ただし、重要な作業も伴います。

于 2013-11-22T09:28:10.867 に答える
2

これは、シードが十分に変化せず、ランダム性がシードに依存するためです。

srand ドキュメントから:

srand の呼び出しで使用されるすべての異なるシード値に対して、疑似乱数ジェネレーターは、その後の rand の呼び出しで異なる一連の結果を生成することが期待できます。

srand編集:事前にシードを生成するか、呼び出しごとに手動でシードを変更してみてください。

于 2013-11-22T09:28:21.743 に答える