psrs_sort.c
上传用户:hhyinxing
上传日期:2013-09-10
资源大小:833k
文件大小:8k
源码类别:

并行计算

开发平台:

Unix_Linux

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <mpi.h>
  4. #define INIT_TYPE 10
  5. #define ALLTOONE_TYPE 100
  6. #define ONETOALL_TYPE 200
  7. #define MULTI_TYPE 300
  8. #define RESULT_TYPE 400
  9. #define RESULT_LEN 500
  10. #define MULTI_LEN 600
  11. int Spt;
  12. long DataSize;
  13. int *arr,*arr1;
  14. int mylength;
  15. int *index;
  16. int *temp1;
  17. main(int argc,char* argv[])
  18. {
  19.     long BaseNum = 1;
  20.     int PlusNum;
  21.     int MyID;
  22.     MPI_Init(&argc,&argv);
  23.     MPI_Comm_rank(MPI_COMM_WORLD,&MyID);
  24.     PlusNum=60;
  25.     DataSize = BaseNum*PlusNum;
  26.     if (MyID==0)
  27.         printf("The DataSize is : %lun",PlusNum);
  28.     Psrs_Main();
  29.     if (MyID==0)
  30.         printf("n");
  31.     MPI_Finalize();
  32. }
  33. Psrs_Main( )
  34. {
  35.     int i,j;
  36.     int MyID,SumID;
  37.     int n,c1,c2,c3,c4,k,l;
  38.     FILE * fp;
  39.     int ready;
  40.     MPI_Status status[32*32*2];
  41.     MPI_Request request[32*32*2];
  42.     MPI_Comm_rank(MPI_COMM_WORLD,&MyID);
  43.     MPI_Comm_size(MPI_COMM_WORLD,&SumID);
  44.     Spt = SumID-1;
  45. /*初始化参数*/
  46.     arr = (int *)malloc(2*DataSize*sizeof(int));
  47.     if (arr==0) merror("malloc memory for arr error!");
  48.     arr1 = &arr[DataSize];
  49.     if (SumID>1)
  50.     {
  51.         temp1 = (int *)malloc(sizeof(int)*SumID*Spt);
  52.         if (temp1==0) merror("malloc memory for temp1 error!");
  53.         index = (int *)malloc(sizeof(int)*2*SumID);
  54.         if (index==0) merror("malloc memory for index error!");
  55.     }
  56.     MPI_Barrier( MPI_COMM_WORLD);
  57.     mylength = DataSize / SumID;
  58.     srand(MyID);
  59.     printf("This is node %d n",MyID);
  60.     printf("On node %d the input data is:n",MyID);
  61.     for (i=0;i<mylength;i++)
  62.     {
  63.         arr[i] = (int)rand();
  64.         printf("%d : ",arr[i]);
  65.     }
  66.     printf("n");
  67. /*每个处理器将自己的n/P个数据用串行快速排序(Quicksort),得到一个排好序的序列,对应于算法13.5步骤(1)*/
  68.     MPI_Barrier( MPI_COMM_WORLD);
  69.     quicksort(arr,0,mylength - 1);
  70.     MPI_Barrier( MPI_COMM_WORLD);
  71. /*每个处理器从排好序的序列中选取第w,2w,3w,…,(P-1)w个共P-1个数据作为代表元素,其中w=n/P*P,对应于算法13.5步骤(2)*/
  72.     if (SumID>1)
  73.     {
  74.         MPI_Barrier(MPI_COMM_WORLD);
  75.         n = (int)(mylength/(Spt+1));
  76.         for (i=0;i<Spt;i++)
  77.             temp1[i] = arr[(i+1)*n-1];
  78.         MPI_Barrier(MPI_COMM_WORLD);
  79.         if (MyID==0)
  80.         {
  81. /*每个处理器将选好的代表元素送到处理器P0中,对应于算法13.5步骤(3) */
  82.             j = 0;
  83.             for (i=1;i<SumID;i++)
  84.                 MPI_Irecv(&temp1[i*Spt], sizeof(int)*Spt, MPI_CHAR, i,ALLTOONE_TYPE+i, MPI_COMM_WORLD, &request[j++]);
  85.             MPI_Waitall(SumID-1, request, status);
  86. /* 处理器P0将上一步送来的P段有序的数据序列做P路归并,再选择排序后的第P-1,2(P-1),…,(P-1)(P-1)个共P-1个主元,,对应于算法13.5步骤(3)*/
  87.             MPI_Barrier(MPI_COMM_WORLD);
  88.             quicksort(temp1,0,SumID*Spt-1);
  89.             MPI_Barrier( MPI_COMM_WORLD);
  90.             for (i=1;i<Spt+1;i++)
  91.                 temp1[i] = temp1[i*Spt-1];
  92. /*处理器P0将这P-1个主元播送到所有处理器中,对应于算法13.5步骤(4)*/
  93.             MPI_Bcast(temp1, sizeof(int)*(1+Spt), MPI_CHAR, 0, MPI_COMM_WORLD);
  94.             MPI_Barrier(MPI_COMM_WORLD);
  95.         }
  96.         else
  97.         {
  98.             MPI_Send(temp1,sizeof(int)*Spt,MPI_CHAR,0,ALLTOONE_TYPE+MyID, MPI_COMM_WORLD);
  99.             MPI_Barrier( MPI_COMM_WORLD);
  100.             MPI_Barrier( MPI_COMM_WORLD);
  101.             MPI_Bcast(temp1, sizeof(int)*(1+Spt), MPI_CHAR, 0, MPI_COMM_WORLD);
  102.             MPI_Barrier(MPI_COMM_WORLD);
  103.         }
  104. /*每个处理器根据上步送来的P-1个主元把自己的n/P个数据分成P段,记为处理器Pi的第j+1段,其中i=0,…,P-1,j=0,…,P-1,对应于算法13.5步骤(5)*/
  105.         n = mylength;
  106.         index[0] = 0;
  107.         i = 1;
  108.         while ((arr[0]>=temp1[i])&&(i<SumID))
  109.         {
  110.             index[2*i-1] = 0;
  111.             index[2*i] = 0;
  112.             i++;
  113.         }
  114.         if (i==SumID) index[2*i-1] = n;
  115.         c1 = 0;
  116.         while (i<SumID)
  117.         {
  118.             c4 = temp1[i];
  119.             c3 = n;
  120.             c2 = (int)((c1+c3)/2);
  121.             while ((arr[c2]!=c4)&&(c1<c3))
  122.             {
  123.                 if (arr[c2]>c4)
  124.                 {
  125.                     c3 = c2-1;
  126.                     c2 = (int)((c1+c3)/2);
  127.                 }
  128.                 else
  129.                 {
  130.                     c1 = c2+1;
  131.                     c2 = (int)((c1+c3)/2);
  132.                 }
  133.             }
  134.             while ((arr[c2]<=c4)&&(c2<n)) c2++;
  135.             if (c2==n)
  136.             {
  137.                 index[2*i-1] = n;
  138.                 for (k=i;k<SumID;k++)
  139.                 {
  140.                     index[2*k] = 0;
  141.                     index[2*k+1] = 0;
  142.                 }
  143.                 i = SumID;
  144.             }
  145.             else
  146.             {
  147.                 index[2*i] = c2;
  148.                 index[2*i-1] = c2;
  149.             }
  150.             c1 = c2;
  151.             c2 = (int)((c1+c3)/2);
  152.             i++;
  153.         }
  154.         if (i==SumID) index[2*i-1] = n;
  155.         MPI_Barrier( MPI_COMM_WORLD);
  156. /*每个处理器送它的第i+1段给处理器Pi,从而使得第i个处理器含有所有处理器的第i段数据(i=0,…,P-1),,对应于算法13.5步骤(6)*/
  157.         j = 0;
  158.         for (i=0;i<SumID;i++)
  159.         {
  160.             if (i==MyID)
  161.             {
  162.                 temp1[i] = index[2*i+1]-index[2*i];
  163.                 for (n=0;n<SumID;n++)
  164.                     if (n!=MyID)
  165.                 {
  166.                     k = index[2*n+1]-index[2*n];
  167.                     MPI_Send(&k, sizeof(int), MPI_CHAR, n, MULTI_LEN+MyID,MPI_COMM_WORLD);
  168.                 }
  169.             }
  170.             else
  171.             {
  172.                 MPI_Recv(&temp1[i], sizeof(int), MPI_CHAR, i,MULTI_LEN+i, MPI_COMM_WORLD, &status[j++]);
  173.             }
  174.         }
  175.         MPI_Barrier(MPI_COMM_WORLD);
  176.         j = 0;
  177.         k = 0;
  178.         l = 0;
  179.         for (i=0;i<SumID;i++)
  180.         {
  181.             MPI_Barrier(MPI_COMM_WORLD);
  182.             if (i==MyID)
  183.             {
  184.                 for (n=index[2*i];n<index[2*i+1];n++)
  185.                     arr1[k++] = arr[n];
  186.             }
  187.             MPI_Barrier(MPI_COMM_WORLD);
  188.             if (i==MyID)
  189.             {
  190.                 for (n=0;n<SumID;n++)
  191.                     if (n!=MyID)
  192.                 {
  193.                     MPI_Send(&arr[index[2*n]], sizeof(int)*(index[2*n+1]-index[2*n]),MPI_CHAR, n, MULTI_TYPE+MyID, MPI_COMM_WORLD);
  194.                 }
  195.             }
  196.             else
  197.             {
  198.                 l = temp1[i];
  199.                 MPI_Recv(&arr1[k], l*sizeof(int), MPI_CHAR, i ,MULTI_TYPE+i, MPI_COMM_WORLD, &status[j++]);
  200.                 k=k+l;
  201.             }
  202.             MPI_Barrier(MPI_COMM_WORLD);
  203.         }
  204.         mylength = k;
  205.         MPI_Barrier(MPI_COMM_WORLD);
  206. /*每个处理器再通过P路归并排序将上一步的到的数据排序;从而这n个数据便是有序的,,对应于算法13.5步骤(7) */
  207.         k = 0;
  208.         multimerge(arr1,temp1,arr,&k,SumID);
  209.         MPI_Barrier(MPI_COMM_WORLD);
  210.     }
  211.     printf("On node %d the sorted data is : n",MyID);
  212.     for (i=0;i<mylength;i++)
  213.         printf("%d : ",arr[i]);
  214.     printf("n");
  215. }
  216. /*输出错误信息*/
  217. merror(char* ch)
  218. {
  219.     printf("%sn",ch);
  220.     exit(1);
  221. }
  222. /*串行快速排序算法*/
  223. quicksort(int *datas,int bb,int ee)
  224. {
  225.     int tt,i,j;
  226.     tt = datas[bb];
  227.     i = bb;
  228.     j = ee;
  229.     if (i<j)
  230.     {
  231.         while(i<j)
  232.         {
  233.             while ((i<j)&&(tt<=datas[j])) j--;
  234.             if (i<j)
  235.             {
  236.                 datas[i] = datas[j];
  237.                 i++;
  238.                 while ((i<j)&&(tt>datas[i])) i++;
  239.                 if (i<j)
  240.                 {
  241.                     datas[j] = datas[i];
  242.                     j--;
  243.                     if (i==j) datas[i] = tt;
  244.                 }
  245.                 else datas[j] = tt;
  246.             } else datas[i] = tt;
  247.         }
  248.         quicksort(datas,bb,i-1);
  249.         quicksort(datas,i+1,ee);
  250.     }
  251. }
  252. /*串行多路归并算法*/
  253. multimerge(int *data1,int *ind,int *data,int *iter,int SumID)
  254. {
  255.     int i,j,n;
  256.     j = 0;
  257.     for (i=0;i<SumID;i++)
  258.         if (ind[i]>0)
  259.     {
  260.         ind[j++] = ind[i];
  261.         if (j<i+1) ind[i] = 0;
  262.     }
  263.     if ( j>1 )
  264.     {
  265.         n = 0;
  266.         for (i=0;i<j,i+1<j;i=i+2)
  267.         {
  268.             merge(&(data1[n]),ind[i],ind[i+1],&(data[n]));
  269.             ind[i] += ind[i+1];
  270.             ind[i+1] = 0;
  271.             n += ind[i];
  272.         }
  273.         if (j%2==1 )
  274.             for (i=0;i<ind[j-1];i++) data[n++]=data1[n];
  275.         (*iter)++;
  276.         multimerge(data,ind,data1,iter,SumID);
  277.     }
  278. }
  279. merge(int *data1,int s1,int s2,int *data2)
  280. {
  281.     int i,l,m;
  282.     l = 0;
  283.     m = s1;
  284.     for (i=0;i<s1+s2;i++)
  285.     {
  286.         if (l==s1)
  287.             data2[i]=data1[m++];
  288.         else
  289.         if (m==s2+s1)
  290.             data2[i]=data1[l++];
  291.         else
  292.         if (data1[l]>data1[m])
  293.             data2[i]=data1[m++];
  294.         else
  295.             data2[i]=data1[l++];
  296.     }
  297. }