2012-03-28 40 views
0

我試圖使用MPI由不同的處理器我想用MPI_Gather收集和後打印所有排序數字排序後的數字進行排序,但是這是行不通的。任何幫助將不勝感激。以下是我的代碼。MPI編程問題與MPI_Gather

#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 2012-03-28 17:58:56

+0

我生成隨機數,並進行排序,但排序後,當我調用MPI_Gather()函數我有一個部分排序列表。例如。我可能有這樣的事情 排序清單:34,35,36,40,1,2,3,10,41,42,43,44:我希望這是有幫助的。 – fanbondi 2012-03-28 18:05:10

+0

我認爲馬克的回答是正確的:你需要某種方式來合併各個部分。我也注意到'relmts'太小了:它應該保存來自所有進程的條目,並且只需要在根目錄下分配。 – 2012-03-28 19:27:31

回答

1

如果我理解你的代碼,你已經收集了分別排序的子列表返回到一個進程到陣列relmnts?然後按照出現的順序打印出來。但我看不到你在排序relmnts時做了什麼。 (我經常不理解其他人的代碼,所以如果我誤解了現在停止閱讀。)

你似乎希望收集會神祕地將排序後的子列表合併到一個排序列表中。這不會發生!您需要自己合併排序後的子列表中的元素,可能是在將它們收集回一個進程之後,或者可能進行某種「級聯收集」。通過這個我的意思是,假設你有32個進程和32個子列表,那麼你可以將進程1和進程2的子列表合併到進程1,3和4到3,..., 31和32到31,那麼你會從過程1和3合併到1,......後5個步驟,你就必須在整個列表合併,排序順序,工藝1(我是一個Fortran程序員,我從1開始算起,我應該寫「的過程與等級0」 )。順便提一下,你在你自己的問題的評論中提供的例子可能是誤導性的:它看起來像你收集3個子列表,每個4個元素並將它們撞在一起。但是,子列表1中沒有元素比子列表2中的任何元素都要小,就是這樣。如果原始列表未排序,這是如何發生的?

+0

感謝您的答覆,但我認爲您所說的已經在CompareSplit函數中完成了,CompareSplit所做的是比較來自奇數和偶數處理器的數字,因爲我使用的是奇數偶數排序方法並將較大數字列表到較高數字處理器並將較低列表保留在較低數字處理器中。所以最後你會根據處理器順序排列所有數字。即處理器0將具有最小數字,以此類推到最後一個具有最大數目的處理器。這就是我想到的。 – fanbondi 2012-03-29 00:49:33