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

并行计算

开发平台:

Unix_Linux

  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("%sn",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 wrongn");
  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 errorn");
  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("%dt%dn", M, N);
  224.         for(i=0;i<M;i++)
  225.         {
  226.             for(j=0;j<M;j++) printf("%ft",A(i,j));
  227.             printf("%fn",B(i));
  228.         }
  229.         printf("nOutput of solutionn");
  230.         for(k=0;k<M;k++)
  231.         {
  232.             for(i=0;i<M;i++)
  233.             {
  234.                 if (shift[i]==k) printf("x[%d]=%fn",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 secondsn",time2-starttime);
  243.         printf("Distribute data time  = %f secondsn",time1-starttime);
  244.         printf("Parallel compute time = %f secondsn",time2-time1);
  245.     }
  246.     MPI_Finalize();
  247.     Environment_Finalize(a,b,x,f);
  248.     return(0);
  249. }