2012-03-28 60 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