并行实验源代码_第1页
并行实验源代码_第2页
并行实验源代码_第3页
并行实验源代码_第4页
并行实验源代码_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

实验一l.Hello.c#include"mpi.h"#include<stdio.h>intmain(intargc,char**argv){MPI_Init(&argc,&argv);printf("helloparallelworld!\n");MPI_Finalize();}一2.isend.c#include<stdio.h>#include<stdlib.h>#include"mpi.h"intmain(intargc,char**argv){inti,numprocs,namelen,myid;charprocessor_name[MPI_MAX_PROCESSOR_NAME];intbuf[5];intflag=0;MPI_Statusstatus;MPI_Requestr;MPI_Init(&argc,&argv);MPI_Comm_rank(MPI_COMM_WORLD,&myid);MPI_Comm_size(MPI_COMM_WORLD,&numprocs);MPI_Get_processor_name(processor_name,&namelen);if(myid==0){for(i=0;i<5;i++){buf[i]=i;}MPI_Isend(&buf,5,MPI_INT,1,99,MPI_COMM_WORLD,&r);}else{MPI_Irecv(&buf,5,MPI_INT,0,99,MPI_COMM_WORLD,&r);MPI_Test(&r,&flag,&status);printf("BeforeMPI_Waitflag=%d.Thebufiscan'tbeused!\n",flag);for(i=0;i<5;i++){printf("buf[%d]=\t%d\n”,i,buf[i]);}MPI_Wait(&r,&status);MPI_Test(&r,&flag,&status);printf("AfterMPI_Waitflag=%d.Thebufiscanbeused!\n",flag);for(i=0;i<5;i++){printf("buf[%d]=\t%d\n",i,buf[i]);}}MPI_Finalize();return0;}message.c#include<stdio.h>#include"mpi.h"intmain(intargc,char**argv){intmyid,numprocs,source;MPI_Statusstatus;charmessage[100];MPI_Init(&argc,&argv);MPI_Comm_rank(MPI_COMM_WORLD,&myid);MPI_Comm_size(MPI_COMM_WORLD,&numprocs);if(myid!=0){strcpy(message,"HelloWorld!");MPI_Send(message,strlen(message)+1,MPI_CHAR,0,99,MPI_COMM_WORLD);}else{for(source=1;source<numprocs;source++){MPI_Recv(message,100,MPI_CHAR,source,99,MPI_COMM_WORLD,&status);printf("Iamprocess%d.Irecvstring'%s'fromprocess%d.\n",myid,message,source);}}MPI_Finalize();}mtpi.c#include"mpi.h”#include<stdio.h>#include<stdlib.h>#include"time.h”main(intargc,char**argv){intmyid,numprocs;intnamelen,source;longcount=1000000;doubley;doublex;longm=0,m1=0,i=0,p=0;doublepi=0.0,n=0.0;charprocessor_name[MPI_MAX_PROCESSOR_NAME];MPI_Statusstatus;MPI_Init(&argc,&argv);MPI_Comm_rank(MPI_COMM_WORLD,&myid);MPI_Comm_size(MPI_COMM_WORLD,&numprocs);MPI_Get_processor_name(processor_name,&namelen);srand((int)time(0));for(i=0;i<count;i++){x=(double)rand()/(double)RAND_MAX;y=(double)rand()/(double)RAND_MAX;if((x-0.5)*(x-0.5)+(y-0.5)*(y-0.5)<0.25)m++;}n=4.0*m/count;printf("Process%dof%don%spi=%f\n",myid,numprocs,processor_name,n);if(myid!=0){MPI_Send(&m,1,MPI_DOUBLE,0,1,MPI_COMM_WORLD);}else{p=m;for(source=1;source<numprocs;source++){MPI_Recv(&m1,1,MPI_DOUBLE,source,1,MPI_COMM_WORLD,&status);p=p+m1;}printf("pi=%f\n”,4.0*p/(count*numprocs));}MPI_Finalize();}5.who.c#include"mpi.h"#include<stdio.h>intmain(intargc,char**argv){intmyid,numprocs;intnamelen;charprocessor_name[MPI_MAX_PROCESSOR_NAME];MPI_Init(&argc,&argv);MPI_Comm_rank(MPI_COMM_WORLD,&myid);MPI_Comm_size(MPI_COMM_WORLD,&numprocs);MPI_Get_processor_name(processor_name,&namelen);printf("HelloWorld!Process%dof%don%s\n",myid,numprocs,processor_name);MPI_Finalize();}一实验二1.共享存储模型#include<stdio.h>#include<stdlib.h>#include<omp.h>#defineN10000intmain(intargc,char*argv[])(inti;intarray[N];intcount,nthreads,tid,chunk;unsignednum;chunk=100;count=0;doublestart,end;printf("pleasechoosenumberofthreads:1,2or4.\n")scanf("%d”,&num);//提示输入计算线程数omp_set_num_threads(num);#pragmaompparallelshared(nthreads)(tid=omp_get_thread_num();if(tid==0)nthreads=omp_get_num_threads();printf("\nStartingcountwith%dthreads\n”,nthreads);}}start=omp_get_wtime();#pragmaompparallelforreduction(+:count)schedule(static,chunk)for(i=0;i<N;i++)(array[i]=rand()%10;if(array[i]==3)count++;}end=omp_get_wtime();printf("Thecountcost%fsec.time.\n",end-start);printf("Thenumberof3appearedinthearrayare%d”,count);}2.消息传递模型#include<time.h>#defineMPICH_SKIP_MPICXX#include<stdio.h>#include"mpi.h"#include"stdlib.h"#defineRrand()#defineN10000intmain(intargc,char**argv){intmyid,numprocs;intarray[N];intcountall=0;MPI_Statusstatus;srand((int)time(0));for(inti=0;i<N;i++){array[i]=rand()%10;}MPI_Init(&argc,&argv);MPI_Comm_rank(MPI_COMM_WORLD,&myid);MPI_Comm_size(MPI_COMM_WORLD,&numprocs);intcount=0,counti=0;for(intj=N/numprocs*myid;j<N/numprocs*myid+N/numprocs;j++){if(array[j]==3)count++;}if(myid!=0)

{MPI_Send(&count,10,MPI_CHAR,0,99,MPI_COMM_WORLD);}else{countall=count;printf("Iamprocess%d,inmyprocessthenumberis%d.\n",myid,count);for(intsource=1;source<numprocs;source++){MPI_Recv(&counti,10,MPI_CHAR,source,99,MPI_COMM_WORLD,&status);countall=countall+counti;printf("Iamprocess%d,Ireceivethenumber%dfrom%d.\n",myid,counti,source);}printf("Iamprocess%d,Thetotalof3fortheallareais%d.\n",myid,countall);}MPI_Finalize();}实验三1.矩阵相乘简单划分并行算法#include"stdio.h"#include"stdlib.h"#include"mpi.h"#defineintsizesizeof(int)#definefloatsizesizeof(float)#definecharsizesizeof(char)#defineA(x,y)A[x*K+y]#defineB(x,y)B[x*N+y]#defineC(x,y)C[x*N+y]#definea(x,y)a[x*K+y]#defineb(x,y)b[x*n+y]#definebuffer(x,y)buffer[x*n+y]/*此宏用来简化对标号为奇数的处理器内的缓冲空间的访问*/float*a,*b,*c,*buffer;ints;float*A,*B,*C;#definec(l,x,y)c[x*N+y+l*n]/*A[M,K],B[P,N].正确的情况下K应该等于P,否则无法

进行矩阵相乘*/intM,N,K,P;intm,n;intmyid;intp;/*保存工作站集群中处理器数目,也即通信子大小*/FILE*dataFile;/*用于读取输入文件内容和将计算结果输出到结果文件的临时文件指针*/MPI_Statusstatus;float*a,*b,*c,*buffer;ints;float*A,*B,*C;函数名:readData*功能:此函数被rankID为0的进程调用,负责从dataIn.txt文件中读入A[M,K],B[P,N]两个相乘矩阵的数据,并为结果矩阵C[M,N]分配空间。其中C[N,N]=A[M,K]*B[P,N]*输入:无*返回值:无*/voidreadData(){inti,j;starttime=MPI_Wtime();dataFile=fopen("dataIn.txt","r");/*读取矩阵A的行,列数/*为矩阵A/*读取矩阵A的行,列数/*为矩阵A分配空间*//*读入矩阵A的各元素*//*读取矩阵B的行,列数P,N/*K应该等于?,否则矩阵A=(float*)malloc(floatsize*M*K);for(i=0;i<M;i++){for(j=0;j<K;j++){fscanf(dataFile,"%f",A+i*K+j);}}fscanf(dataFile,"%d%d",&P,&N);*/if(K!=P)无法相乘*/{printf("theinputiswrong\n");exit(1);

}B=(float*)malloc(floatsize*K*N);for(i=0;i<K;i++)素*/{for(j=0;j<N;j++){fscanf(dataFile,"%f”,B+i*N+j);}}fclose(dataFile);printf("Inputoffile\"dataIn.txt\"\n");printf("%d\t%d\n",M,K);for(i=0;i<M;i++){for(j=0;j<K;j++)printf("%f\t",A(i,j));printf("\n");}printf("%d\t%d\n",K,N);for(i=0;i<K;i++){for(j=0;j<N;j++)printf("%f\t",B(i,j));printf("\n");}C=(float*)malloc(floatsize*M*N);间*//*为矩阵B分配空间*//*/*为矩阵B分配空间*//*从文件中读入矩阵B的各元/*输出A矩阵的维数*//*输出A矩阵的数据*//*输出B矩阵的维数*//*输出B矩阵的数据*//*为结果矩阵C[M,N]分配空*函数名:gcd*功能:此函数用来返回两个整数的不大于group_size的最大公因子*输入:M,N:要求最大公因数的两个整数*group_size所求公因子必须小于此参数,此参数代表用户指定的通信子大小*返回值:M和N的不大于group_size的最大公因子*/intgcd(intM,intN,intgroup_size){inti;for(i=M;i>0;i--){if((M%i==0)&&(N%i==0)&&(i<=group_size))returni;}return1;}/*函数名:printResult*功能:此函数被rankID为0的进程调用,用来将A,B,C矩阵打印输出给用户,并输出用于分发数据和并行计算的时间*输入:无*返回值:无*/voidprintResult(){inti,j;printf("\nOutputofMatrixC=AB\n");for(i=0;i<M;i++)/*输出C矩阵的结果数据*/{for(j=0;j<N;j++)printf("%f\t",C(i,j));printf("\n");}endtime=MPI_Wtime();printf("\n");printf("Wholerunningtime=%fseconds\n",endtime-starttime);printf("Distributedatatime=%fseconds\n",time1-starttime);printf("Parallelcomputetime=%fseconds\n",endtime-time1);}/**函数名:main*功能:程序的主函数*输入:argc为命令行参数个数;*argv为每个命令行参数组成的字符串数组。*输出:返回0代表程序正常结束;其它值表明程序出错。*/intmain(intargc,char**argv){

inti,j,k,l,group_size,mp1,mm1;MPI_Init(&argc,&argv);MPI_Comm_size(MPI_COMM_WORLD,&group_size);MPI_Comm_rank(MPI_COMM_WORLD,&myid);p=group_size;//下面一段程序负责从dataIn.txt文件中读入A[M,K],B[P,N]两个相乘矩阵的数据,//并为结果矩阵C[M,N]分配空间。C[N,N]=A[M,K]*B[P,N]〃注意这段程序只有编号为0的处理器才执行此步操作if(myid==0){readData();}if(myid==0)/*由编号为0的进程将A,B两矩阵的行列维数M,K,N发送给所有其他进程*/for(i=1;i<p;i++){MPI_Send(&M,1,MPI_INT,i,i,MPI_COMM_WORLD);MPI_Send(&K,1,MPI_INT,i,i,MPI_COMM_WORLD);MPI_Send(&N,1,MPI_INT,i,i,MPI_COMM_WORLD);}else/*编号非0的进程负责接收A,B两矩阵的行列维数M,K,N*/{MPI_Recv(&M,1,MPI_INT,0,myid,MPI_COMM_WORLD,&status);MPI_Recv(&K,1,MPI_INT,0,myid,MPI_COMM_WORLD,&status);MPI_Recv(&N,1,MPI_INT,0,myid,MPI_COMM_WORLD,&status);}p=gcd(M,N,group_size);/*m代表将矩阵按行/*m/*m代表将矩阵按行/*m代表将矩阵按列/*a[m,K]用来存储本处理器/*b[K,n]用来存储此时处理器n=N/p;分块后每块的列数*/if(myid<p){a=(float*)malloc(floatsize*m*K);拥有的矩阵A的行块*/b=(float*)malloc(floatsize*K*n);拥有的矩阵B的列块*/c=(float*)malloc(floatsize*m*N);/*c[m,N]用来存储本处理器计算p-1次得到所有结果*/if(myid%2!=0)/*为标号为奇数的处理器分配发送缓冲空间*/buffer=(float*)malloc(K*n*floatsize);if(a==NULL||b==NULL||c==NULL)/*如果分配空间出错,则打印出错信息*/printf("Allocatespacefora,borcfail!");if(myid==0)/*标号为0的处理器将应该它拥有的矩阵A,B的元素读入自己的a,b中*/{for(i=0;i<m;i++)for(j=0;j<K;j++)a(i,j)=A(i,j);for(i=0;i<K;i++)for(j=0;j<n;j++)b(i,j)=B(i,j);}if(myid==0)/*标号为0的处理器将其他处理器的初始数据分别发给各处理器*/{for(i=1;i<p;i++){MPI_Send(&A(m*i,0),K*m,MPI_FLOAT,i,i,MPI_COMM_WORLD);for(j=0;j<K;j++)MPI_Send(&B(j,n*i),n,MPI_FLOAT,i,i,MPI_COMM_WORLD);}free(A);free(B);/*至此,A,B两矩阵的数据已经完全被分散到各处理器。释放A,B所占空间*/}else/*标号非0的处理器从0处理器接受各自的初始矩阵数据*/{MPI_Recv(a,K*m,MPI_FLOAT,0,myid,MPI_COMM_WORLD,&status);for(j=0;j<K;j++)MPI_Recv(&b(j,0),n,MPI_FLOAT,0,myid,MPI_COMM_WORLD,&status);}if(myid==0)time1=MPI_Wtime();/*标号为0的处理器记录开始矩阵相乘计算的时间*/for(i=0;i<p;i++)/*一共进行p轮计算*/{l=(i+myid)%p;for(k=0;k<m;k++)for(j=0;j<n;j++)for(c(l,k,j)=0,s=0;s<K;s++)c(l,k,j)+=a(k,s)*b(s,j);mm1=(p+myid-1)%p;/*计算本进程的前一个进程的标号*/mp1=(myid+1)%p;/*计算本进程的后一个进程的标号*/if(i!=p-1){if(myid%2==0)/*偶数号处理器先发送后接收*/{MPI_Send(b,K*n,MPI_FLOAT,mm1,mm1,MPI_COMM_WORLD);MPI_Recv(b,K*n,MPI_FLOAT,mp1,myid,MPI_COMM_WORLD,&status);}else/*奇数号处理器先将B的列块存于缓冲区buffer中,然后接收编号在其后面的处理器所发送的B的列块,最后再将缓冲区中原矩阵B的列块发送给编号在其前面的处理器*/{for(k=0;k<K;k++)for(j=0;j<n;j++)buffer(k,j)=b(k,j);MPI_Recv(b,K*n,MPI_FLOAT,mp1,myid,MPI_COMM_WORLD,&status);MPI_Send(buffer,K*n,MPI_FLOAT,mm1,mm1,MPI_COMM_WORLD);}}}if(myid==0)/*标号为0的进程直接将计算结果保存到结果矩阵C中*/for(i=0;i<m;i++)for(j=0;j<N;j++)C(i,j)=*(c+i*N+j);if(myid!=0)/*标号非0的进程则要把计算结果发送到标号为0的处理器中去*/MPI_Send(c,m*N,MPI_FLOAT,0,myid,MPI_COMM_WORLD);else/*标号为0的进程负责接收其他进程的计算结果并保存到结果矩阵C中*/{for(k=1;k<p;k++){MPI_Recv(c,m*N,MPI_FLOAT,k,k,MPI_COMM_WORLD,&status);for(i=0;i<m;i++)for(j=0;j<N;j++)C((k*m+i),j)=*(c+i*N+j);}}if(myid==0)/*0号处理器负责将A,B,C矩阵打印输出给用户,并输出用于分发数据和并行计算的时间*/printResult();}MPI_Finalize();if(myid<p)/*释放所有临时分配空间*/{free(a);free(b);free(c);if(myid==0)/*只有0号进程要释放C*/free(C);if(myid%2!=0)/*只有奇数号进程要释放buffer*/free(buffer);return(0);2.cannon算法#include<stdlib.h>#include<string.h>#include<mpi.h>#include<time.h>#include<stdio.h>#include<math.h>/*全局变量声明*/float**A,**B,**C;/*总矩阵,C=A*B*/float*a,*b,*c,*tmp_a,*tmp_b;/*a、b、c表分块,tmp_a、tmp_b表缓冲区*/intdg,dl,dl2,p,sp;/*dg:总矩阵维数;dl:矩阵块维数;dl2=dl*dl;p:处理器个数;sp=sqrt(p)*/intmy_rank,my_row,my_col;/*my_rank:处理器ID;(my_row,my_col):处理器逻辑阵列坐标*/一--MPI_Statusstatus;/**函数名:get_index*功能:处理器逻辑阵列坐标至rank号的转换*输入:坐标、逻辑阵列维数*输出:rank号*/intget_index(introw,intcol,intsp)(一return((row+sp)%sp)*sp+(col+sp)%sp;}/**函数名:random_A_B*功能:随机生成矩阵A和B*/voidrandom_A_B(){inti,j;srand((unsignedint)time(NULL));/*设随机数种子*//*随机生成A,B,并初始化C*/for(i=0;i<dg;i++)for(j=0;j<dg;j++){A[i][j]=rand();B[i][j]=rand();C[i][j]=0.0;}}/*函数名:scatter_A_B*功能:rank为0一的处理器向其他处理器发送A、B矩阵的相关块*/voidscatter_A_B(){inti,j,k,l;intp_imin,p_imax,p_jmin,p_jmax;for(k=0;k<p;k++){/*计算相应处理器所分得的矩阵块在总矩阵中的坐标范围*/p_jmin=(k%sp)*dl;p_jmax=(k%sp+1)*dl-1;p_imin=(k-(k%sp))/sp*dl;p_imax=((k-(k%sp))/sp+1)*dl-1;l=0;/*rank=0的处理器将A,B中的相应块拷至tmp_a,tmp_b,准备向其他处理器发送*/for(i=p_imin;i<=p_imax;i++){for(j=p_jmin;j<=p_jmax;j++){tmp_a[l]=A[i][j];tmp_b[l]=B[i][j];l++;}}/*rank=0的处理器直接将自己对应的矩阵块从tmp_a,tmp_b拷至a,b*/if(k==0){memcpy(a,tmp_a,dl2*sizeof(float));memcpy(b,tmp_b,dl2*sizeof(float));}else/*rank=0的处理器向其他处理器发送tmp_a,tmp_b中相关的矩阵块*/{MPI_Send(tmp_a,dl2,MPI_FLOAT,k,1,MPI_COMM_WORLD);MPI_Send(tmp_b,dl2,MPI_FLOAT,k,2,MPI_COMM_WORLD);}}}/**函数名:init_alignment*功能:矩阵A和B初始对准*/voidinit_alignment(){/*将A中坐标为(i,j)的分块A(i,j)向左循环移动i步*/MPI_Sendrecv(a,dl2,MPI_FLOAT,get_index(my_row,my_col-my_row,sp),1,tmp_a,dl2,MPI_FLOAT,get_index(my_row,my_col+my_row,sp),1,MPI_COMM_WORLD,&status);memcpy(a,tmp_a,dl2*sizeof(float));/*将B中坐标为(i,j)的分块B(i,j)向上循环移动j步*/MPI_Sendrecv(b,dl2,MPI_FLOAT,get_index(my_row-my_col,my_col,sp),1,tmp_b,dl2,MPI_FLOAT,get_index(my_row+my_col,my_col,sp),1,MPI_COMM_WORLD,&status);memcpy(b,tmp_b,dl2*sizeof(float));}/**函数名:main_shift*功能:分块矩阵左移和上移,并计算分块c*/voidmain_shift(){inti,j,k,l;for(l=0;l<sp;l++){/*矩阵块相乘,c+=a*b*/for(i=0;i<dl;i++)for(j=0;j<dl;j++)for(k=0;k<dl;k++)c[i*dl+j]+=a[i*dl+k]*b[k*dl+j];/*将分块a左移1位*/MPI_Send(a,dl2,MPI_FLOAT,get_index(my_row,my_col-1,sp),1,MPI_COMM_WORLD);MPI_Recv(a,dl2,MPI_FLOAT,get_index(my_row,my_col+1,sp),1,MPI_COMM_WORLD,&status);/*将分块b上移1位*/MPI_Send(b,dl2,MPI_FLOAT,get_index(my_row-1,my_col,sp),1,MPI_COMM_WORLD);MPI_Recv(b,dl2,MPI_FLOAT,get_index(my_row+1,my_col,sp),1,MPI_COMM_WORLD,&status);}}/**函数名:collect_c*功能:rank为j的处理器从其余处理器收集分块矩阵c*/voidcollect_C()(一inti,j,i2,j2,k;intp_imin,p_imax,p_jmin,p_jmax;/*分块矩阵在总矩阵中顶点边界值*//*将rank为0的处理器中分块矩阵c结果赋给总矩阵C对应位置*/for(i=0;i<dl;i++)for(j=0;j<dl;j++)C[i][j]=c[i*dl+j];for(k=1;k<p;k++){/*将rank为0的处理器从其他处理器接收相应的分块c*/MPI_Recv(c,dl2,MPI_FLOAT,k,1,MPI_COMM_WORLD,&status);p_jmin=(k%sp)*dl;p_jmax=(k%sp+1)*dl-1;p_imin=(k-(k%sp))/sp*dl;p_imax=((k-(k%sp))/sp+1)*dl-1;i2=0;/*将接收到的c拷至C中的相应位置,从而构造出C*/for(i=p_imin;i<=p_imax;i++){j2=0;for(j=p_jmin;j<=p_jmax;j++){C[i][j]=c[i2*dl+j2];j2++;}i2++;}}}/*函数名:print*功能:打印矩阵*输入:指向矩阵指针的指针,字符串*/voidprint(float**m,char*str){inti,j;printf("%s",str);/*打印矩阵m*/for(i=0;i<dg;i++){for(j=0;j<dg;j++)printf("%15.0f",m[i][j]);printf("\n");}printf("\n");}/**函数名:main*功能:主过程,Cannon算法,矩阵相乘*输入:argc为命令行参数个数,argv为每个命令行参数组成的字符串数组*/intmain(intargc,char*argv[]){inti;MPI_Init(&argc,&argv);/*启动MPI计算*/MPI_Comm_size(MPI_COMM_WORLD,&p);/*确定处理器个数*/MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);/*确定各自的处理器标识符*/sp=sqrt(p);/*确保处理器个数是完全平方数,否则打印错误信息,程序退出*/if(sp*sp!=p)if(my_rank==0)printf("Numberofprocessorsi

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论