gauss.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. #include "stdio.h"
  2. #include "stdlib.h"
  3. #include "mpi.h"
  4. #include "math.h"
  5. #define a(x,y) a[x*M+y]
  6. #define b(x) b[x]
  7. #define A(x,y) A[x*M+y]
  8. #define B(x) B[x]
  9. #define floatsize sizeof(float)
  10. #define intsize sizeof(int)
  11. int M;
  12. int N;
  13. int m;
  14. float *A;
  15. float *B;
  16. double starttime;
  17. double time1;
  18. double time2;
  19. int my_rank;
  20. int p;
  21. int l;
  22. MPI_Status status;
  23. void fatal(char *message)
  24. {
  25. printf("%s\n",message);
  26. exit(1);
  27. }
  28. void Environment_Finalize(float *a,float *b,float *x,float *f)
  29. {
  30. free(a);
  31. free(b);
  32. free(x);
  33. free(f);
  34. }
  35. int main(int argc, char **argv)
  36. {
  37. int i,j,t,k,my_rank,group_size;
  38. int i1,i2;
  39. int v,w;
  40. float temp;
  41. int tem;
  42. float *sum;
  43. float *f;
  44. float lmax;
  45. float *a;
  46. float *b;
  47. float *x;
  48. int *shift;
  49. FILE *fdA,*fdB;
  50. MPI_Init(&argc,&argv);
  51. MPI_Comm_size(MPI_COMM_WORLD,&group_size);
  52. MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
  53. p=group_size;
  54. if (my_rank==0)
  55. {
  56. starttime=MPI_Wtime();
  57. fdA=fopen("dataIn.txt","r");
  58. fscanf(fdA,"%d %d", &M, &N);
  59. if (M != N-1)
  60. {
  61. printf("the input is wrong\n");
  62. exit(1);
  63. }
  64. A=(float *)malloc(floatsize*M*M);
  65. B=(float *)malloc(floatsize*M);
  66. for(i = 0; i < M; i++)
  67. {
  68. for(j = 0; j < M; j++)
  69. {
  70. fscanf(fdA,"%f", A+i*M+j);
  71. }
  72. fscanf(fdA,"%f", B+i);
  73. }
  74. fclose(fdA);
  75. }
  76. MPI_Bcast(&M,1,MPI_INT,0,MPI_COMM_WORLD); /* 0号处理机将M广播给所有处理机 */
  77. m=M/p;
  78. if (M%p!=0) m++;
  79. f=(float*)malloc(sizeof(float)*(M+1)); /* 各处理机为主行元素建立发送和接收缓冲区(M+1) */
  80. a=(float*)malloc(sizeof(float)*m*M); /* 分配至各处理机的子矩阵大小为m*M */
  81. b=(float*)malloc(sizeof(float)*m); /* 分配至各处理机的子向量大小为m */
  82. sum=(float*)malloc(sizeof(float)*m);
  83. x=(float*)malloc(sizeof(float)*M);
  84. shift=(int*)malloc(sizeof(int)*M);
  85. if (a==NULL||b==NULL||f==NULL||sum==NULL||x==NULL||shift==NULL)
  86. fatal("allocate error\n");
  87. for(i=0;i<M;i++)
  88. shift[i]=i;
  89. /*
  90. 0号处理机采用行交叉划分将矩阵A划分为大小为m*M的p块子矩阵,将B划分为大小
  91. 为m的p块子向量,依次发送给1至p-1号处理机
  92. */
  93. if (my_rank==0)
  94. {
  95. for(i=0;i<m;i++)
  96. for(j=0;j<M;j++)
  97. a(i,j)=A(i*p,j);
  98. for(i=0;i<m;i++)
  99. b(i)=B(i*p);
  100. }
  101. if (my_rank==0)
  102. {
  103. for(i=0;i<M;i++)
  104. if ((i%p)!=0)
  105. {
  106. i1=i%p;
  107. i2=i/p+1;
  108. MPI_Send(&A(i,0),M,MPI_FLOAT,i1,i2,MPI_COMM_WORLD);
  109. MPI_Send(&B(i),1,MPI_FLOAT,i1,i2,MPI_COMM_WORLD);
  110. }
  111. } /* my_rank==0 */
  112. else /* my_rank !=0 */
  113. {
  114. for(i=0;i<m;i++)
  115. {
  116. MPI_Recv(&a(i,0),M,MPI_FLOAT,0,i+1,MPI_COMM_WORLD,&status);
  117. MPI_Recv(&b(i),1,MPI_FLOAT,0,i+1,MPI_COMM_WORLD,&status);
  118. }
  119. }
  120. time1=MPI_Wtime(); /* 开始计时 */
  121. for(i=0;i<m;i++) /* 消去 */
  122. for(j=0;j<p;j++)
  123. {
  124. if (my_rank==j) /* j号处理机负责广播主行元素 */
  125. {
  126. v=i*p+j; /* 主元素在原系数矩阵A中的行号和列号为v */
  127. lmax=a(i,v);
  128. l=v;
  129. for(k=v+1;k<M;k++) /* 在同行的元素中找最大元,并确定最大元所在的列l */
  130. if (fabs(a(i,k))>lmax)
  131. {
  132. lmax=a(i,k);
  133. l=k;
  134. }
  135. if (l!=v) /* 列交换 */
  136. {
  137. for(t=0;t<m;t++)
  138. {
  139. temp=a(t,v);
  140. a(t,v)=a(t,l);
  141. a(t,l)=temp;
  142. }
  143. tem=shift[v];
  144. shift[v]=shift[l];
  145. shift[l]=tem;
  146. }
  147. for(k=v+1;k<M;k++) /* 归一化 */
  148. a(i,k)=a(i,k)/a(i,v);
  149. b(i)=b(i)/a(i,v);
  150. a(i,v)=1;
  151. for(k=v+1;k<M;k++)
  152. f[k]=a(i,k);
  153. f[M]=b(i);
  154. /* 发送归一化后的主行 */
  155. MPI_Bcast(&f[0],M+1,MPI_FLOAT,my_rank,MPI_COMM_WORLD);
  156. /* 发送主行中主元素所在的列号 */
  157. MPI_Bcast(&l,1,MPI_INT,my_rank,MPI_COMM_WORLD);
  158. }
  159. else
  160. {
  161. v=i*p+j;
  162. MPI_Bcast(&f[0],M+1,MPI_FLOAT,j,MPI_COMM_WORLD);
  163. MPI_Bcast(&l,1,MPI_INT,j,MPI_COMM_WORLD);
  164. if (l!=v)
  165. {
  166. for(t=0;t<m;t++)
  167. {
  168. temp=a(t,v);
  169. a(t,v)=a(t,l);
  170. a(t,l)=temp;
  171. }
  172. tem=shift[v];
  173. shift[v]=shift[l];
  174. shift[l]=tem;
  175. }
  176. }
  177. if (my_rank<=j)
  178. for(k=i+1;k<m;k++)
  179. {
  180. for(w=v+1;w<M;w++)
  181. a(k,w)=a(k,w)-f[w]*a(k,v);
  182. b(k)=b(k)-f[M]*a(k,v);
  183. }
  184. if (my_rank>j)
  185. for(k=i;k<m;k++)
  186. {
  187. for(w=v+1;w<M;w++)
  188. a(k,w)=a(k,w)-f[w]*a(k,v);
  189. b(k)=b(k)-f[M]*a(k,v);
  190. }
  191. } /* for i j */
  192. for(i=0;i<m;i++)
  193. sum[i]=0.0;
  194. for(i=m-1;i>=0;i--) /* 回代 */
  195. for(j=p-1;j>=0;j--)
  196. if (my_rank==j)
  197. {
  198. x[i*p+j]=(b(i)-sum[i])/a(i,i*p+j);
  199. MPI_Bcast(&x[i*p+j],1,MPI_FLOAT,my_rank,MPI_COMM_WORLD);
  200. for(k=0;k<i;k++)
  201. sum[k]=sum[k]+a(k,i*p+j)*x[i*p+j];
  202. }
  203. else
  204. {
  205. MPI_Bcast(&x[i*p+j],1,MPI_FLOAT,j,MPI_COMM_WORLD);
  206. if (my_rank>j)
  207. for(k=0;k<i;k++)
  208. sum[k]=sum[k]+a(k,i*p+j)*x[i*p+j];
  209. if (my_rank<j)
  210. for(k=0;k<=i;k++)
  211. sum[k]=sum[k]+a(k,i*p+j)*x[i*p+j];
  212. }
  213. if (my_rank!=0)
  214. for(i=0;i<m;i++)
  215. MPI_Send(&x[i*p+my_rank],1,MPI_FLOAT,0,i,MPI_COMM_WORLD);
  216. else
  217. for(i=1;i<p;i++)
  218. for(j=0;j<m;j++)
  219. MPI_Recv(&x[j*p+i],1,MPI_FLOAT,i,j,MPI_COMM_WORLD,&status);
  220. if (my_rank==0)
  221. {
  222. printf("Input of file \"dataIn.txt\"\n");
  223. printf("%d\t%d\n", M, N);
  224. for(i=0;i<M;i++)
  225. {
  226. for(j=0;j<M;j++) printf("%f\t",A(i,j));
  227. printf("%f\n",B(i));
  228. }
  229. printf("\nOutput of solution\n");
  230. for(k=0;k<M;k++)
  231. {
  232. for(i=0;i<M;i++)
  233. {
  234. if (shift[i]==k) printf("x[%d]=%f\n",k,x[i]);
  235. }
  236. }
  237. }
  238. time2=MPI_Wtime();
  239. if (my_rank==0)
  240. {
  241. printf("\n");
  242. printf("Whole running time = %f seconds\n",time2-starttime);
  243. printf("Distribute data time = %f seconds\n",time1-starttime);
  244. printf("Parallel compute time = %f seconds\n",time2-time1);
  245. }
  246. MPI_Finalize();
  247. Environment_Finalize(a,b,x,f);
  248. return(0);
  249. }