歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> MPI 實現並行直接插入排序

MPI 實現並行直接插入排序

日期:2017/3/1 10:13:46   编辑:Linux編程

話說 直插排序串行只需要十幾行 並行就大不一樣。。。

基本思路是

1/主線程控制數據讀取 分發和匯總

2/從線程中數據按線程號非降有序 每次有新數據 主線程廣播 從線程按照數據大小判斷是否在自己處理范圍內 如果在的話 在自己保存的數組中進行直接插入

3/最後 主線程按序收集顯示所有數據

  1. #include "mpi.h"
  2. #include <unistd.h>
  3. #include <fcntl.h>
  4. #include <ctype.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #define END 0
  8. #define INIT 1
  9. #define DATA 2
  10. #define ROOT 0
  11. int readValue(char* file,int* values)
  12. {
  13. int fd,size,count=0;
  14. char buffer[80],num[11];
  15. fd=open(file,O_RDONLY);
  16. do
  17. {
  18. size=read(fd,buffer,sizeof(buffer));
  19. int j=0;
  20. for(int i=0;i<size;++i)
  21. {
  22. if(buffer[i]<'9'&&buffer[i]>'0')
  23. {
  24. num[j++]=buffer[i];
  25. }else
  26. {
  27. num[j]='\0';
  28. values[count++]=atoi(num);
  29. j=0;
  30. }
  31. }
  32. }while(size!=0);
  33. close(fd);
  34. return count;
  35. }
  36. void insert(int* arr,int pos,int temp)
  37. {
  38. while(pos>=0&&temp<arr[pos])
  39. {
  40. arr[pos+1]=arr[pos];
  41. --pos;
  42. }
  43. arr[pos+1]=temp;
  44. }
  45. void serial(int* arr,int size)
  46. {
  47. for(int i=1;i<size;++i)
  48. {
  49. insert(arr,i-1,arr[i]);
  50. }
  51. }
  52. int main(int argc,char *argv[])
  53. {
  54. int* values;
  55. int self,size,length,temp;
  56. MPI_Init(&argc,&argv);
  57. MPI_Comm_size(MPI_COMM_WORLD,&size);
  58. MPI_Comm_rank(MPI_COMM_WORLD,&self);
  59. MPI_Status status;
  60. if(self==0)
  61. {
  62. //read value from file
  63. values=(int*)malloc(100*sizeof(int));
  64. length=readValue("/home/gt/parellel/sort/data.in",values);
  65. //initial root value of each process
  66. serial(values,size);
  67. //broadcast the max length of each process
  68. MPI_Bcast(&length,1,MPI_INT,ROOT,MPI_COMM_WORLD);
  69. //the boundary
  70. for(int i=1;i<size;++i)
  71. {
  72. MPI_Ssend(&values[i-1],1,MPI_INT,i,INIT,MPI_COMM_WORLD);
  73. }
  74. MPI_Recv(&temp,1,MPI_INT,self+1,DATA,MPI_COMM_WORLD,&status);
  75. //broadcast each value and do insert in each process
  76. for(int i=size-1;i<length;++i)
  77. {
  78. temp=values[i];
  79. MPI_Bcast(&temp,1,MPI_INT,ROOT,MPI_COMM_WORLD);
  80. printf("broadcast %d \n",values[i]);
  81. //MPI_Barrier(MPI_COMM_WORLD);
  82. }
  83. //ends
  84. printf("ends \n");
  85. temp=END;
  86. MPI_Bcast(&temp,1,MPI_INT,ROOT,MPI_COMM_WORLD);
  87. //recieve from each process in order
  88. int pos=0;
  89. int len=0;
  90. for(int i=1;i<size;++i)
  91. {
  92. MPI_Recv(&len,1,MPI_INT,i,DATA,MPI_COMM_WORLD,&status);
  93. for(int j=0;j<len;++j)
  94. {
  95. MPI_Recv(&temp,1,MPI_INT,i,DATA,MPI_COMM_WORLD,&status);
  96. values[pos++]=temp;
  97. }
  98. }
  99. for(int i=0;i<length;++i)
  100. {
  101. printf("%d \n",values[i]);
  102. }
  103. free(values);
  104. }
  105. else
  106. {
  107. MPI_Request request;
  108. //recieve max length
  109. MPI_Bcast(&length,1,MPI_INT,ROOT,MPI_COMM_WORLD);
  110. //position
  111. int pos=0;
  112. //post irecv
  113. MPI_Irecv(&temp,1,MPI_INT,ROOT,INIT,MPI_COMM_WORLD,&request);
  114. //data on this process
  115. int* local=(int*) malloc(length*sizeof(int)+1);
  116. //wait for the recieve
  117. MPI_Wait(&request,&status);
  118. //exchange upper limit
  119. int upper=999999;//max of int
  120. if(self!=size-1)MPI_Irecv(&upper,1,MPI_INT,self+1,DATA,MPI_COMM_WORLD,&request);
  121. MPI_Ssend(&temp,1,MPI_INT,self-1,DATA,MPI_COMM_WORLD);
  122. if(self!=size-1)MPI_Wait(&request,&status);
  123. local[pos++]=temp;
  124. MPI_Bcast(&temp,1,MPI_INT,ROOT,MPI_COMM_WORLD);
  125. //MPI_Barrier(MPI_COMM_WORLD);
  126. while(temp!=END)
  127. {
  128. printf("%d recieve %d \n",self,temp);
  129. if(temp<=upper&&(self==1||local[0]<temp))
  130. {
  131. printf("%d insert %d \n",self,temp);
  132. local[pos++]=temp;
  133. insert(local,pos-2,temp);
  134. }
  135. MPI_Bcast(&temp,1,MPI_INT,ROOT,MPI_COMM_WORLD);
  136. //MPI_Barrier(MPI_COMM_WORLD);
  137. }
  138. //ends
  139. //sends the data in order to root process
  140. MPI_Ssend(&pos,1,MPI_INT,ROOT,DATA,MPI_COMM_WORLD);
  141. for(int i=0;i<pos;++i)
  142. {
  143. MPI_Ssend(&local[i],1,MPI_INT,ROOT,DATA,MPI_COMM_WORLD);
  144. printf("% d send back %d \n",self,local[i]);
  145. }
  146. free(local);
  147. }
  148. MPI_Finalize();
  149. return 0;
  150. }
Copyright © Linux教程網 All Rights Reserved