歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> MPI 堆排序

MPI 堆排序

日期:2017/3/1 10:12:58   编辑:Linux編程

堆排是串行排序中最適合並行化的排序之一

1/分為主線程和從線程
2/主線程分發數據,使用大小與從線程個數相同的堆作為私有堆,進行最後整理用
3/從線程維護一個堆,每次返回給主線程堆頂元素
4/主線程 提取堆頂元素 通知相應從線程提交新的堆頂元素
5/主從線程並行進行重建堆(heapify)的動作

  1. #include "mpi.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #define ROOT 0
  5. #define TAG 0
  6. #define NEXT 1
  7. #define END -1
  8. typedef struct node {
  9. int v;
  10. int r;
  11. } Node;
  12. static inline int left(int i) {
  13. return i*2+1;
  14. }
  15. static inline int right(int i) {
  16. return left(i)+1;
  17. }
  18. void defineIntVector(MPI_Datatype* type,int length) {
  19. MPI_Type_vector(length,1,1,MPI_INT,type);
  20. MPI_Type_commit(type);
  21. }
  22. //for slaves
  23. void heapifyI(int *a,int root,int size) {
  24. int l=left(root);
  25. int r=right(root);
  26. int m=root;
  27. if(l<size&&a[l]<a[m]) {
  28. m=l;
  29. }
  30. if(r<size&&a[r]<a[m]) {
  31. m=r;
  32. }
  33. if(m!=root) {
  34. int t=a[root];
  35. a[root]=a[m];
  36. a[m]=t;
  37. heapifyI(a,m,size);
  38. }
  39. }
  40. void buildHeapI(int *a,int size) {
  41. for(int i=(size-1)/2;i>=0;--i) {
  42. heapifyI(a,i,size);
  43. }
  44. }
  45. //for root
  46. void heapifyN(Node *a,int root,int size) {
  47. int l=left(root);
  48. int r=right(root);
  49. int m=root;
  50. if(l<size&&a[l].v<a[m].v) {
  51. m=l;
  52. }
  53. if(r<size&&a[r].v<a[m].v) {
  54. m=r;
  55. }
  56. if(m!=root) {
  57. Node t=a[root];
  58. a[root]=a[m];
  59. a[m]=t;
  60. heapifyN(a,m,size);
  61. }
  62. }
  63. void buildHeapN(Node *a,int size) {
  64. for(int i=(size-1)/2;i>=0;--i) {
  65. heapifyN(a,i,size);
  66. }
  67. }
  68. int main(int argc,char *argv[]) {
  69. int self,size;
  70. int part;//threshold
  71. MPI_Init(&argc,&argv);
  72. MPI_Comm_rank(MPI_COMM_WORLD,&self);
  73. MPI_Comm_size(MPI_COMM_WORLD,&size);
  74. MPI_Status status;
  75. MPI_Datatype MPI_VEC;
  76. if(ROOT==self) {
  77. //all data
  78. int values[]={1,5,3,8,4,2,9,6,7,54,34,6,13,63,32,14,53,21,65,33,24,213,23,14,21,65,32};
  79. int length=27;
  80. //for each process
  81. part=length/(size-1);
  82. MPI_Bcast(&part,1,MPI_INT,ROOT,MPI_COMM_WORLD);
  83. defineIntVector(&MPI_VEC,part);
  84. //heap for min value from each process
  85. Node *nodes=(Node*)malloc((size-1)*sizeof(Node));
  86. for(int i=0;i<size-1;++i) {
  87. nodes[i].r=i+1;
  88. }
  89. //send out all the data
  90. for(int i=1;i<size;++i) {
  91. MPI_Ssend(&values[(i-1)*part],1,MPI_VEC,i,TAG,MPI_COMM_WORLD);
  92. }
  93. for(int i=1;i<size;++i) {
  94. MPI_Recv(&(nodes[i-1].v),1,MPI_INT,i,TAG,MPI_COMM_WORLD,&status);
  95. }
  96. //end flag
  97. part=size-1;
  98. //build a heap representing process
  99. buildHeapN(nodes,part);
  100. int p=0;
  101. while(part>0) {
  102. values[p++]=nodes[0].v;
  103. //similar to the message passing system of select sort
  104. MPI_Ssend(&p,1,MPI_INT,nodes[0].r,NEXT,MPI_COMM_WORLD);
  105. MPI_Recv(&(nodes[0].v),1,MPI_INT,nodes[0].r,TAG,MPI_COMM_WORLD,&status);
  106. if(END==nodes[0].v) {
  107. nodes[0]=nodes[--part];
  108. }
  109. heapifyN(nodes,0,part);
  110. }
  111. for(int i=0;i<length;++i)
  112. printf("%d ",values[i]);
  113. free(nodes);
  114. } else {
  115. MPI_Bcast(&part,1,MPI_INT,ROOT,MPI_COMM_WORLD);
  116. defineIntVector(&MPI_VEC,part);
  117. int *values=(int*)malloc(part*sizeof(int));
  118. MPI_Recv(values,1,MPI_VEC,ROOT,TAG,MPI_COMM_WORLD,&status);
  119. buildHeapI(values,part);
  120. //send the smallest
  121. MPI_Ssend(&values[0],1,MPI_INT,ROOT,TAG,MPI_COMM_WORLD);
  122. //pop out one
  123. values[0]=values[--part];
  124. //rebuild heap
  125. heapifyI(values,0,part);
  126. while(part>0) {
  127. MPI_Recv(&values[part],1,MPI_INT,ROOT,NEXT,MPI_COMM_WORLD,&status);
  128. MPI_Ssend(&values[0],1,MPI_INT,ROOT,TAG,MPI_COMM_WORLD);
  129. values[0]=values[--part];
  130. heapifyI(values,0,part);
  131. }
  132. MPI_Recv(&values[part],1,MPI_INT,ROOT,NEXT,MPI_COMM_WORLD,&status);
  133. values[0]=END;
  134. MPI_Ssend(&values[0],1,MPI_INT,ROOT,TAG,MPI_COMM_WORLD);
  135. free(values);
  136. }
  137. MPI_Finalize();
  138. return 0;
  139. }
Copyright © Linux教程網 All Rights Reserved