2012-03-28 3 views
0

異なるプロセッサでソートした後で、数値をソートするためにMPIを使用しようとしていますが、MPI_Gatherを使用してすべてのソートされた数値を収集し、どんな助けもありがとう。以下は私のコードです。MPI_GatherでのMPIプログラミングの問題

#include <stdio.h> 
#include <time.h> 
#include <math.h> 
#include <stdlib.h> 
#include <mpi.h> /* Include MPI's header file */ 

    /* The IncOrder function that is called by qsort is defined as follows */ 
    int IncOrder(const void *e1, const void *e2) 
    { 
     return (*((int *)e1) - *((int *)e2)); 
    } 
    void CompareSplit(int nlocal, int *elmnts, int *relmnts, int *wspace, int keepsmall); 
//int IncOrder(const void *e1, const void *e2); 
int main(int argc, char *argv[]){ 
     int n;   /* The total number of elements to be sorted */ 
     int npes;  /* The total number of processes */ 
     int myrank; /* The rank of the calling process */ 
      int nlocal; /* The local number of elements, and the array that stores them */ 
     int *elmnts; /* The array that stores the local elements */ 
      int *relmnts; /* The array that stores the received elements */ 
     int oddrank; /* The rank of the process during odd-phase communication */ 
     int evenrank; /* The rank of the process during even-phase communication */ 
     int *wspace; /* Working space during the compare-split operation */ 
     int i; 
     MPI_Status status; 

     /* Initialize MPI and get system information */ 
     MPI_Init(&argc, &argv); 
     MPI_Comm_size(MPI_COMM_WORLD, &npes); 
     MPI_Comm_rank(MPI_COMM_WORLD, &myrank); 

     n = 30000;//atoi(argv[1]); 
     nlocal = n/npes; /* Compute the number of elements to be stored locally. */ 

     /* Allocate memory for the various arrays */ 
     elmnts = (int *)malloc(nlocal*sizeof(int)); 
     relmnts = (int *)malloc(nlocal*sizeof(int)); 
     wspace = (int *)malloc(nlocal*sizeof(int)); 

     /* Fill-in the elmnts array with random elements */ 
     srand(time(NULL)); 
     for (i=0; i<nlocal; i++) { 
       elmnts[i] = rand()%100+1; 
      printf("\n%d:",elmnts[i]); //print generated random numbers 
     } 

      /* Sort the local elements using the built-in quicksort routine */ 
       qsort(elmnts, nlocal, sizeof(int), IncOrder); 
        /* Determine the rank of the processors that myrank needs to communicate during 
      * ics/ccc.gifthe */ 
      /* odd and even phases of the algorithm */ 
      if (myrank%2 == 0) { 
       oddrank = myrank-1; 
       evenrank = myrank+1; 
      } else { 
       oddrank = myrank+1; 
       evenrank = myrank-1; 
             } 

      /* Set the ranks of the processors at the end of the linear */ 
      if (oddrank == -1 || oddrank == npes) 
       oddrank = MPI_PROC_NULL; 
      if (evenrank == -1 || evenrank == npes) 
       evenrank = MPI_PROC_NULL; 

      /* Get into the main loop of the odd-even sorting algorithm */ 
      for (i=0; i<npes-1; i++) { 
       if (i%2 == 1) /* Odd phase */ 
        MPI_Sendrecv(elmnts, nlocal, MPI_INT, oddrank, 1, relmnts, 
        nlocal, MPI_INT, oddrank, 1, MPI_COMM_WORLD, &status); 
       else /* Even phase */ 
        MPI_Sendrecv(elmnts, nlocal, MPI_INT, evenrank, 1, relmnts, 
        nlocal, MPI_INT, evenrank, 1, MPI_COMM_WORLD, &status); 

        CompareSplit(nlocal, elmnts, relmnts, wspace, myrank < status.MPI_SOURCE); 
      } 

     MPI_Gather(elmnts,nlocal,MPI_INT,relmnts,nlocal,MPI_INT,0,MPI_COMM_WORLD); 


     /* The master host display the sorted array */ 
     //int len = sizeof(elmnts)/sizeof(int); 
     if(myrank == 0) { 

      printf("\nSorted array :\n"); 
      int j; 
      for (j=0;j<n;j++) { 
      printf("relmnts[%d] = %d\n",j,relmnts[j]); 
     } 

     printf("\n"); 
     //printf("sorted in %f s\n\n",((double)clock() - start)/CLOCKS_PER_SEC); 
     } 


       free(elmnts); free(relmnts); free(wspace); 
      MPI_Finalize(); 
    } 

    /* This is the CompareSplit function */ 
    void CompareSplit(int nlocal, int *elmnts, int *relmnts, int *wspace, int keepsmall){ 
     int i, j, k; 
      for (i=0; i<nlocal; i++) 
       wspace[i] = elmnts[i]; /* Copy the elmnts array into the wspace array */ 

      if (keepsmall) { /* Keep the nlocal smaller elements */ 
      for (i=j=k=0; k<nlocal; k++) { 
       if (j == nlocal || (i < nlocal && wspace[i] < relmnts[j])) 
        elmnts[k] = wspace[i++]; 
       else 
        elmnts[k] = relmnts[j++]; 
      } 
     } else { /* Keep the nlocal larger elements */ 
       for (i=k=nlocal-1, j=nlocal-1; k>=0; k--) { 
        if (j == 0 || (i >= 0 && wspace[i] >= relmnts[j])) 
         elmnts[k] = wspace[i--]; 
       else 
        elmnts[k] = relmnts[j--]; 
      } 
     } 
    } 
+0

どのように「機能しませんか」 – suszterpatt

+0

私は乱数を生成し、ソートを行いますが、ソート後にMPI_Gather()関数を呼び出すと、部分ソート済みリストが得られます。例えば。私はこのようなものを持っているかもしれません ソートリスト:34,35,36,40,1,2,3,10,41,42,43,44:私はそれが役に立ちそうです。 – fanbondi

+0

Markの答えは正しいと思います。個々の部分をマージするには何らかの方法が必要です。私は 'relmts'が小さすぎることにも気付きました。それはすべてのプロセスからのエントリを保持する必要があり、ルートでのみ割り当てられる必要があります。 –

答えて

1

私はあなたのコードを理解していればあなたは、配列relmntsに戻って一つのプロセスへの個別ソートサブリストを集めてきましたか?そして、それらを発生順に印刷した。しかし、私はあなたが並べ替えについて何かしたのを見ることができませんrelmnts。 (私はしばしば他の人のコードを理解していないので、今読んでいると誤解している場合)

あなたはソートされたサブリストを不思議な形でソートリストにマージすることを望んでいるようです。それは起こるつもりはない!可能であれば、ソートされたサブリストから要素をマージする必要があります。おそらく、それらを1つのプロセスに集めた後、ある種の「カスケードギャザー」を実行した後です。

これはつまり、32個のプロセスと32個のサブリストがあったとすると、プロセス1とプロセス2のサブリストをプロセス1,3,4に3、...、 31と32を31に置きます。次に、プロセス1と3を1にマージします。5つのステップを実行すると、プロセス1でソートされた順番でリスト全体がマージされます(私はFortranプログラマーです1でカウントを開始すると、「ランク0のプロセス」と書かれているはずですなど)。

ちなみに、自分の質問にあなたのコメントを入れた例は誤解を招くかもしれません。あなたが4つの要素のそれぞれを3つのサブリストを集めてまとめたように見えます。しかし、サブリスト1には、サブリスト2のどの要素よりも小さい要素はありません。そのようなものです。元のリストがソートされていないとどうなりましたか?

+0

あなたの答えはMarkさんにありがとうございますが、あなたが言っていることはCompareSplit関数で既に行われていると思います。CompareSplitの機能は、奇数と偶数のプロセッサからの数値を比較することです。上位プロセッサにリストし、下位プロセッサを下位プロセッサに保つ。したがって、最後には、プロセッサーに応じてすべての数値を並べ替えることになります。即ち、プロセッサ0は、最も小さい数を有し、最大数を有する最後のプロセッサまで続く。それは私がそれについて考えた方法です。 – fanbondi

関連する問題