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

并行计算

开发平台:

Unix_Linux

  1. /**输入邻接矩阵和源顶点,求最短路径。输入邻接矩阵中,位置(x,y)为顶点y到x的边权**/
  2. #include <mpi.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. /**定义M为无穷大**/
  7. #define M 1.7e308
  8. #define BOOL int
  9. #define FALSE 0
  10. #define TRUE  1
  11. #define W(x,y) W[x*nodenum+y]
  12. FILE* fp;
  13. char ch;
  14. char id[20];
  15. int point;
  16. double* W;
  17. double* dist;
  18. BOOL* bdist;
  19. int nodenum = 0;
  20. int S = 0;
  21. /* show err and exit*/
  22. void fatal(char* err)
  23. {
  24. printf("%s/n", err);
  25. exit(0);
  26. }
  27. /**从文件中读取字符**/
  28. void GetChar()
  29. {
  30. fread(&ch,sizeof(char),1,fp);
  31. }
  32. /**读取一个小数,如果为字符M或m,令其值为无穷大**/
  33. double GetNextNum()
  34. {
  35. double num;
  36. while(!isdigit(ch) && ch!='M' && ch!='m')
  37. GetChar();
  38. if(isdigit(ch))
  39. {
  40. point = 0;
  41. while(isdigit(ch))
  42. {
  43. id[point] = ch;
  44. point ++;
  45. GetChar();
  46. }
  47. id[point] = 0;
  48. num = atof(id);
  49. }else{
  50. num = M;
  51. GetChar();
  52. }
  53. return num;
  54. }
  55. /**读入邻接矩阵**/
  56. void ReadMatrix()
  57. {
  58. char file[40];
  59. int i,j;
  60. double num;
  61. printf("Begin to read the matrix!n");
  62. printf("The first integer of the file should be the size of the matrix!n");
  63. printf("Input the file name of the matrix:");
  64. scanf("%s",file);
  65. if((fp = fopen(file,"r")) == NULL)
  66. {
  67. fatal("File name input error!");
  68. }
  69. num = GetNextNum();
  70. if(num < 0 || num > 10000)
  71. {
  72. fclose(fp);
  73. fatal("The matrix row input error!");
  74. }
  75. nodenum = (int)num;
  76. printf("Input the start node:");
  77. scanf("%d",&S);
  78. if(S >= nodenum) fatal("The start node input too big!n");
  79. W = (double*)malloc(sizeof(double)*num*num);
  80. if( W == NULL)
  81. {
  82. fclose(fp);
  83. fatal("Dynamic allocate space for matrix fail!");
  84. }
  85. for(i=0;i<nodenum;i++)
  86. for(j=0;j<nodenum;j++)
  87. {
  88. W(i,j) = GetNextNum();
  89. }
  90. fclose(fp);
  91. printf("Finish reading the matrix,the nodenum is: %d;n",nodenum);
  92. }
  93. /**各处理器数据初始化**/
  94. void Init(int my_rank,int group_size,int ep)
  95. {
  96. int i;
  97. MPI_Status status;
  98. if(my_rank == 0)
  99. {
  100. for(i=1;i<group_size;i++)
  101. {
  102. MPI_Send(&W(ep*(i-1),0),ep*nodenum,MPI_DOUBLE,i,i,MPI_COMM_WORLD);
  103. }
  104. }else{
  105. dist = (double*)malloc(sizeof(double)*ep);
  106. bdist = (int*) malloc(sizeof(BOOL)*ep);
  107. W = (double*)malloc(sizeof(double)*ep*nodenum);
  108. if(W == NULL || dist == NULL || bdist == NULL)
  109. fatal("Dynamic allocate space for matrix fail!");
  110. MPI_Recv(W,ep*nodenum,MPI_DOUBLE,0,my_rank,MPI_COMM_WORLD,&status);
  111. for(i=0;i<ep; i++)
  112. {
  113. if(i+(my_rank-1)*ep == S)
  114. {
  115. dist[i] = 0;
  116. bdist[i] = TRUE;
  117. }else{
  118. dist[i] = W(i,S);
  119. bdist[i] = FALSE;
  120. }
  121. }
  122. }
  123. }
  124. /**输出邻接矩阵**/
  125. void OutPutMatrix(int my_rank,int group_size,int ep,int mynum)
  126. {
  127. int i,j;
  128. if(my_rank != 0)
  129. {
  130. for(i=0;i<mynum;i++)
  131. {
  132. printf("Processor %d:t",my_rank);
  133. for(j=0;j<nodenum;j++)
  134. {
  135. if(W(i,j) > 1000000) printf("Mt");
  136. else printf("%dt",(int)W(i,j));
  137. }
  138. printf("n");
  139. }
  140. }
  141. }
  142. /**输出结果**/
  143. void OutPutResult(int my_rank,int group_size,int ep,int mynum)
  144. {
  145. int i,j;
  146. if(my_rank != 0)
  147. {
  148. for(i=0;i<mynum;i++)
  149. {
  150. printf("node  %d:t%dn",(my_rank-1)*ep+i,(int)dist[i]);
  151. }
  152. }
  153. }
  154. /**算法主循环**/
  155. void FindMinWay(int my_rank,int group_size,int ep,int mynum)
  156. {
  157. int i,j;
  158. int index,index2;
  159. double num,num2;
  160. int calnum;
  161. MPI_Status status;
  162. int p = group_size;
  163. for(i=0; i<nodenum;i++)
  164. {
  165. index = 0;
  166. num = M;
  167. /**步骤(3.1)**/
  168. for(j=0;j<mynum;j++)
  169. {
  170. if(dist[j] < num && bdist[j]==FALSE)
  171. {
  172. num = dist[j];
  173. index = ep*(my_rank-1)+j;
  174. }
  175. }
  176. MPI_Barrier(MPI_COMM_WORLD);
  177. /**步骤(3.2)**/
  178. calnum = group_size-1;
  179. while(calnum > 1)
  180. {
  181. /**节点数目为偶数时**/
  182. if(calnum % 2 == 0)
  183. {
  184. calnum = calnum/2;
  185. if(my_rank > calnum)
  186. {
  187. MPI_Send(&index,1,MPI_INT,my_rank-calnum,
  188. my_rank-calnum,MPI_COMM_WORLD);
  189. MPI_Send(&num,1,MPI_DOUBLE,my_rank-calnum,
  190. my_rank-calnum,MPI_COMM_WORLD);
  191. }else if(my_rank!=0){
  192. MPI_Recv(&index2,1,MPI_INT,my_rank+calnum,my_rank,
  193. MPI_COMM_WORLD,&status);
  194. MPI_Recv(&num2,1,MPI_DOUBLE,my_rank+calnum,my_rank,
  195. MPI_COMM_WORLD,&status);
  196. if(num2 < num)
  197. {
  198. num = num2;
  199. index = index2;
  200. }
  201. }
  202. }else{
  203. /**节点数目为奇数时**/
  204. calnum = (calnum+1)/2;
  205. if(my_rank > calnum)
  206. {
  207. MPI_Send(&index,1,MPI_INT,my_rank-calnum,
  208. my_rank-calnum,MPI_COMM_WORLD);
  209. MPI_Send(&num,1,MPI_DOUBLE,my_rank-calnum,
  210. my_rank-calnum,MPI_COMM_WORLD);
  211. }else if(my_rank!=0 && my_rank < calnum){
  212. MPI_Recv(&index2,1,MPI_INT,my_rank+calnum,my_rank,
  213. MPI_COMM_WORLD,&status);
  214. MPI_Recv(&num2,1,MPI_DOUBLE,my_rank+calnum,my_rank,
  215. MPI_COMM_WORLD,&status);
  216. if(num2 < num)
  217. {
  218. num = num2;
  219. index = index2;
  220. }
  221. }
  222. }
  223. MPI_Barrier(MPI_COMM_WORLD);
  224. }
  225. /**步骤(3.3)**/
  226. MPI_Bcast(&index,1,MPI_INT,1,MPI_COMM_WORLD);
  227. MPI_Bcast(&num,  1,MPI_DOUBLE,1,MPI_COMM_WORLD);
  228. /**步骤(3.4)**/
  229. for(j=0;j<mynum;j++)
  230. {
  231. if((bdist[j]==FALSE)&&(num + W(j,index) < dist[j]))
  232. dist[j] =num  + W(j,index);
  233. }
  234. /**步骤(3.5)**/
  235. if(my_rank == index/ep+1)
  236. {
  237. bdist[index%ep] = TRUE;
  238. }
  239. MPI_Barrier(MPI_COMM_WORLD);
  240. }
  241. }
  242. /**主函数**/
  243. int main(int argc,char** argv)
  244. {
  245. int group_size,my_rank;
  246. MPI_Status status;
  247. int i,j;
  248. int ep;
  249. int mynum;
  250. MPI_Init(&argc,&argv);/*MPI begin*/
  251. MPI_Comm_size(MPI_COMM_WORLD,&group_size);
  252. MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
  253. /*
  254. if(group_size <= 1)
  255. {
  256. printf("Not enough processor!n");
  257. exit(0);
  258. }
  259. */
  260. /**步骤(1)**/
  261. if(my_rank == 0)
  262. {
  263. ReadMatrix();
  264. for(i=1;i<group_size;i++)
  265. {
  266. MPI_Send(&nodenum,1,MPI_INT,i,i,MPI_COMM_WORLD);
  267. MPI_Send(&S,1,MPI_INT,i,i,MPI_COMM_WORLD);
  268. }
  269. }else{
  270. MPI_Recv(&nodenum,1,MPI_INT,0,my_rank,MPI_COMM_WORLD,&status);
  271. MPI_Recv(&S,1,MPI_INT,0,my_rank,MPI_COMM_WORLD,&status);
  272. }
  273. ep = nodenum/(group_size-1);
  274. if(ep*group_size-ep < nodenum) ep++;
  275. if(ep*my_rank <= nodenum)
  276. {
  277. mynum = ep;
  278. }else if(ep*my_rank < nodenum+ep)
  279. {
  280. mynum = nodenum - ep*(my_rank-1);
  281. }
  282. else mynum = 0;
  283. if (my_rank == 0) mynum = 0;
  284.     /**步骤(2)**/
  285. Init(my_rank,group_size,ep);
  286. OutPutMatrix(my_rank, group_size, ep, mynum);
  287. /**步骤(3)**/
  288. FindMinWay(my_rank,group_size,ep,mynum);
  289. OutPutResult(my_rank,group_size,ep,mynum);
  290. MPI_Finalize();
  291. free(W);
  292. free(dist);
  293. free(bdist);
  294. return 0;
  295. }