2017-10-27 12 views
0

Pi近似のためのこのC MPIアプリケーションは、ランダムに生成されたドットの数である問題サイズごとに常に同じ結果を出力します(npts)。Pi近似のためにこのC MPIアプリケーションを実行すると、結果は常に同じですか?

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include "mpi.h" 

int main(int argc, char *argv[]) { 

    int myid,nprocs; 

    double PI25DT = 3.141592653589793238462643; 

    long long npts = 1e10; 

    long i,mynpts; 

    long double f,sum,mysum; 
    long double xmin,xmax,x; 

    MPI_Init(&argc,&argv); 
    MPI_Comm_size(MPI_COMM_WORLD,&nprocs); 
    MPI_Comm_rank(MPI_COMM_WORLD,&myid); 

    if (myid == 0) { 
    mynpts = npts - (nprocs-1)*(npts/nprocs); 
    } else { 
    mynpts = npts/nprocs; 
    } 

    mysum = 0.0; 
    xmin = 0.0; 
    xmax = 1.0; 

    srand(myid); 

    for (i=0; i<mynpts; i++) { 
    x = (long double) rand()/RAND_MAX*(xmax-xmin) + xmin; 
    mysum += 4.0/(1.0 + x*x); 
    } 

    MPI_Reduce(&mysum,&sum,1,MPI_LONG_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD); 

    if (myid == 0) { 
    f = sum/npts; 
    printf("PI calculated with %lld points = %.16f \n",npts,f); 
    printf("Error is: %.16f \n",fabs(f-PI25DT)); 
    } 

    MPI_Finalize(); 
} 

これは出力です。私は結果がアプリケーションの実行ごとに少し異なると思う。私は128のノードを持つクラスタ上でそれを実行します。あなたはここにPRNGを播種している

$ mpicc pi.c -o /mnt/cluster_128/pi 
$ mpirun -np 128 --hostfile hosts_4cores_128.mpi /mnt/cluster_128/pi 
PI calculated with 10000000000 points = 3.1415901444578158 
Error is: 0.0000025091319773 
$ mpirun -np 128 --hostfile hosts_4cores_128.mpi /mnt/cluster_128/pi 
PI calculated with 10000000000 points = 3.1415901444578158 
Error is: 0.0000025091319773 
$ mpirun -np 128 --hostfile hosts_4cores_128.mpi /mnt/cluster_128/pi 
PI calculated with 10000000000 points = 3.1415901444578158 
Error is: 0.0000025091319773 
$ mpirun -np 128 --hostfile hosts_4cores_128.mpi /mnt/cluster_128/pi 
PI calculated with 10000000000 points = 3.1415901444578158 
Error is: 0.0000025091319773 

答えて

3

srand(myid); 

myidMPI_Comm_rank()にあなたの呼び出しによって設定された値であり、あなたがmyid == 0の結果で唯一の興味が、これは常に同じ値であります。同じ値をシードすると、同じ「乱数」のシーケンスが得られます。

ではなく、播種の一般的なイディオムを使用します。if (myid == 0)あなたのRNGのシードは無用であることを示しているとき

#include <time.h> 
#include <stdlib.h> 

[...] 

srand(time(0)); 
+0

これは 'MPI_Comm_rank'の出力です。 –

+0

@WeatherVaneは播種に適していますか?この答えを削除します... –

+0

いいえ、コードは 'if(myid == 0)' –

1

あなたのコードは、任意の結果を出力します。

私は

srand((unsigned)time(NULL)); 
1

を示唆して、既存の答えはすでに正しい方向を指して、私は彼らの説明は完全に右ではないと思います。

問題は、すでに述べたように、RNGの種です。 myidsrandのシードとして使用しています。これは常に0N-1の間の数値です(Nの番号、つまりmpiexec -np N executableコマンドに渡す番号)。これは確定的です。異なる実行に対しては変更されません。

  • 単一プロセス(Nの場合:したがって、すべてのNプロセスはシードの同じセットを作成しようとしている、および発生した乱数がプロセスの同じ数で同じであるとしている

    = 1):シード値は常に0です。

  • 5つのプロセス(N = 5)の場合、シード値は各プロセスで常に0,1,2,3および4です。等々。

MPI_Reduce集団は、(ランダム番号が同じであることに起因する同じ値を生じる)各プロセスからの全ての部分的な結果を収集し、ルートプロセス(myid=0)グランド和を出力します。 myidのプロセスが結果を出力するかどうかは関係ありません。印刷される最終結果に寄与する異なるmyid値を持つ他のN-1プロセスがあるためです。

myidで2つのプロセスのための小さな例:

  • をランク0srand(0)、(mysum)部分和を計算し、sum変数に他のプロセス部分和を蓄積(rootとして0を指定MPI_Reduce第7引数に結果を出力します(myid==0true

  • ランク1srand(1)、部分和(mysum)をMPI_Reduceルートプロセス(0)に送信します。結果を印刷しません(myid==0false)。

あなたはMPIと理解する必要がある最も重要なことは、あなたが一般的に複数のプロセスに単一のプログラムを実行することで、これらのプロセスのそれぞれは、異なる環境MPI_Comm_rankの出力引数)を取得します。

関連する問題