并行实验源代码

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验一
1.Hello.c
#include "mpi.h"
#include <stdio.h>
int main(int argc,char **argv)
{
MPI_Init(&argc,&argv);
printf("hello parallel world!\n");
MPI_Finalize();
}
2.isend.c
#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"
int main(int argc,char **argv)
{
int i, numprocs,namelen,myid;
char processor_name[MPI_MAX_PROCESSOR_NAME];
int buf[5];
int flag=0;
MPI_Status status;
MPI_Request r;
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("Before MPI_Wait flag=%d. The buf is can't be used!\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("After MPI_Wait flag=%d. The buf is can be used!\n",flag);
for(i=0;i<5;i++)
{
printf("buf[%d]=\t%d \n",i,buf[i]);
}
}
MPI_Finalize( );
return 0;
}
3.message.c
#include <stdio.h>
#include "mpi.h"
int main(int argc, char** argv)
{
int myid,numprocs, source;
MPI_Status status;
char message[100];
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
if (myid != 0)
{
strcpy(message, "Hello World!");
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("I am process %d. I recv string '%s' from process %d.\n", myid,message,source);
}
}
MPI_Finalize();
}
4.mtpi.c
#include"mpi.h"
#include <stdio.h>
#include <stdlib.h>
main(int argc,char **argv)
{
int myid, numprocs;
int namelen,source;
long count=1000000;
double y;
double x;
long m=0,m1=0,i=0,p=0;
double pi=0.0,n=0.0;
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Status status;
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 %d of %d on %s pi= %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"
int main(int argc,char **argv)
{
int myid, numprocs;
int namelen;
char processor_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("Hello World! Process %d of %d on %s\n",myid, numprocs, processor_name);
MPI_Finalize();
}
实验二
1.共享存储模型
#include<stdio.h>
#include<stdlib.h>
#include<omp.h>
#define N 10000
int main(int argc, char *argv[])
{ int i;
int array[N];
int count, nthreads, tid, chunk;
unsigned num;
chunk = 100;
count = 0;
double start, end;
printf("please choose number of threads: 1, 2 or 4.\n")
scanf("%d", &num); //提示输入计算线程数
omp_set_num_threads(num);
#pragma omp parallel shared(nthreads)
{ tid=omp_get_thread_num();
if(tid==0)
nthreads=omp_get_num_threads();
printf("\nStarting count with %d threads\n",nthreads);
}
}
start = omp_get_wtime();
#pragma omp parallel for reduction(+:count) schedule(static,chunk) for( i=0; i<N; i++)
{
array[i] = rand()% 10 ;
if(array[i]==3) count++ ;
}
end =omp_get_wtime();
printf("The count cost %f sec. time.\n", end-start );
printf("The number of 3 appeared in the array are %d", count); }
2.消息传递模型
#include <time.h>
#define MPICH_SKIP_MPICXX
#include <stdio.h>
#include "mpi.h"
#include "stdlib.h"
#define R rand()
#define N 10000
int main(int argc, char** argv)
{
int myid,numprocs;
int array[N];
int countall=0;
MPI_Status status;
srand((int)time(0));
for(int i=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);
int count=0,counti=0;
for(int j=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("I am process %d,in my process the number is %d.\n", myid,count);
for (int source = 1; source < numprocs; source++)
{
MPI_Recv(&counti, 10, MPI_CHAR, source, 99,MPI_COMM_WORLD, &status); countall=countall+counti;
printf("I am process %d,I receive the number %d from %d.\n", myid,counti,source); }
printf("I am process %d,The total of 3 for the all area is %d.\n", myid,countall);
}
MPI_Finalize();
}
实验三
1.矩阵相乘简单划分并行算法
#include "stdio.h"
#include "stdlib.h"
#include "mpi.h"
#define intsize sizeof(int)
#define floatsize sizeof(float)
#define charsize sizeof(char)
#define A(x,y) A[x*K+y]
#define B(x,y) B[x*N+y]
#define C(x,y) C[x*N+y]
#define a(x,y) a[x*K+y]
#define b(x,y) b[x*n+y]
#define buffer(x,y) buffer[x*n+y] /* 此宏用来简化对标号为奇数的处理器内的缓冲空间的访问*/
#define c(l,x,y) c[x*N+y+l*n]
float *a,*b,*c,*buffer;
int s;
float *A,*B,*C; /* A[M,K],B[P,N].正确的情况下K应该等于P,否则无法
进行矩阵相乘*/
int M,N,K,P ;
int m,n;
int myid;
int p; /* 保存工作站集群中处理器数目,也即通信子大小*/
FILE *dataFile; /* 用于读取输入文件内容和将计算结果输出到结果文件的临时文件指针*/
MPI_Status status;
double time1;
double starttime,endtime;
/*
* 函数名: readData
* 功能:此函数被rankID为0的进程调用,负责从dataIn.txt文件中读入
* A[M,K],B[P,N]两个相乘矩阵的数据,并为结果矩阵C[M,N]分配空间。

* 其中C[N,N]=A[M,K]*B[P,N]
* 输入:无
* 返回值:无
*/
void readData()
{
int i,j;
starttime = MPI_Wtime();
dataFile=fopen("dataIn.txt","r");
fscanf(dataFile,"%d%d", &M, &K); /* 读取矩阵A的行,列数M,K */
A=(float *)malloc(floatsize*M*K); /* 为矩阵A分配空间*/
for(i = 0; i < M; i++) /* 读入矩阵A的各元素*/ {
for(j = 0; j < K; j++)
{
fscanf(dataFile,"%f", A+i*K+j);
}
}
fscanf(dataFile,"%d%d", &P, &N); /* 读取矩阵B的行,列数P,N */
if (K!=P) /* K应该等于P,否则矩阵无法相乘*/
{
printf("the input is wrong\n");
exit(1);
}
B=(float *)malloc(floatsize*K*N); /* 为矩阵B分配空间*/
for(i = 0; i < K; i++) /* 从文件中读入矩阵B的各元素*/
{
for(j = 0; j < N; j++)
{
fscanf(dataFile,"%f", B+i*N+j);
}
}
fclose(dataFile);
printf("Input of file \"dataIn.txt\"\n");
printf("%d\t %d\n",M, K); /* 输出A矩阵的维数*/ for(i=0;i<M;i++) /* 输出A矩阵的数据*/ {
for(j=0;j<K;j++) printf("%f\t",A(i,j));
printf("\n");
}
printf("%d\t %d\n",K, N); /* 输出B矩阵的维数*/ for(i=0;i<K;i++) /* 输出B矩阵的数据*/ {
for(j=0;j<N;j++) printf("%f\t",B(i,j));
printf("\n");
}
C=(float *)malloc(floatsize*M*N); /* 为结果矩阵C[M,N]分配空间*/
}
/*
* 函数名: gcd
* 功能:此函数用来返回两个整数的不大于group_size的最大公因子
* 输入:M,N:要求最大公因数的两个整数
* group_size所求公因子必须小于此参数,此参数代表用户指定的通信子大小
* 返回值:M和N的不大于group_size的最大公因子
*/
int gcd(int M,int N,int group_size)
{
int i;
for(i=M; i>0; i--)
{
if((M%i==0)&&(N%i==0)&&(i<=group_size))
return i;
}
return 1;
}
/*
* 函数名: printResult
* 功能:此函数被rankID为0的进程调用,用来将A,B,C矩阵打印输出给用户,* 并输出用于分发数据和并行计算的时间
* 输入:无
* 返回值:无
*/
void printResult()
{
int i,j;
printf("\nOutput of Matrix C = 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("Whole running time = %f seconds\n",endtime-starttime);
printf("Distribute data time = %f seconds\n",time1-starttime);
printf("Parallel compute time = %f seconds\n",endtime-time1);
}
/*
* 函数名: main
* 功能:程序的主函数
* 输入:argc为命令行参数个数;
* argv为每个命令行参数组成的字符串数组。

* 输出:返回0代表程序正常结束;其它值表明程序出错。

*/
int main(int argc, char **argv)
{
int i,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/p; /* m代表将矩阵按行分块后每块的行数*/
n=N/p; /* m代表将矩阵按列分块后每块的列数*/
if(myid<p)
{
a=(float *)malloc(floatsize*m*K); /* a[m,K]用来存储本处理器拥有的矩阵A的行块*/
b=(float *)malloc(floatsize*K*n); /* b[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("Allocate space for a,b or c fail!");
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表缓冲区*/ int dg, dl, dl2,p, sp; /* dg:总矩阵维数;dl:矩阵块维数;dl2=dl*dl;p:处理器个数;sp=sqrt(p) */
int my_rank, my_row, my_col; /* my_rank:处理器ID;(my_row,my_col):处理器逻辑阵列坐标*/
MPI_Status status;
/*
*函数名: get_index
*功能:处理器逻辑阵列坐标至rank号的转换
*输入:坐标、逻辑阵列维数
*输出:rank号
*/
int get_index(int row, int col, int sp)
{
return ((row+sp)%sp)*sp + (col+sp)%sp;
}
/*
*函数名:random_A_B
*功能:随机生成矩阵A和B
*/
void random_A_B()
{
int i,j;
srand((unsigned int)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矩阵的相关块
*/
void scatter_A_B()
{
int i,j,k,l;
int p_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初始对准
*/
void init_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
*/
void main_shift()
{
int i,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为0的处理器从其余处理器收集分块矩阵c
*/
void collect_C()
{
int i,j,i2,j2,k;
int p_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
*功能:打印矩阵
*输入:指向矩阵指针的指针,字符串
*/
void print(float **m,char *str)
{
int i,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为每个命令行参数组成的字符串数组
*/
int main(int argc, char *argv[])
{
int i;
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("Number of processors is not a quadratic number!\n");
MPI_Finalize();
exit(1);
}
if (argc != 2)
{
if (my_rank == 0)
printf("usage: mpirun -np ProcNum cannon MatrixDimension\n");
MPI_Finalize();
exit(1);
}
dg = atoi(argv[1]); /* 总矩阵维数*/
dl = dg / sp; /* 计算分块矩阵维数*/
dl2 = dl * dl;
/* 计算处理器在逻辑阵列中的坐标*/
my_col = my_rank % sp ;
my_row = (my_rank-my_col) / sp ;
/* 为a、b、c分配空间*/
a = (float *)malloc( dl2 * sizeof(float) );
b = (float *)malloc( dl2 * sizeof(float) );
c = (float *)malloc( dl2 * sizeof(float) );
/* 初始化c */
for(i=0; i<dl2 ; i++)
c[i] = 0.0;
/* 为tmp_a、tmp_b分配空间*/
tmp_a = (float *)malloc( dl2 * sizeof(float) );
tmp_b = (float *)malloc( dl2 * sizeof(float) );
if (my_rank == 0)
{
/* rank为0的处理器为A、B、C分配空间*/
A = (float **)malloc( dg * sizeof(float*) );
B = (float **)malloc( dg * sizeof(float*) );
C = (float **)malloc( dg * sizeof(float*) );
for(i=0; i<dg; i++)
{
A[i] = (float *)malloc( dg * sizeof(float) );
B[i] = (float *)malloc( dg * sizeof(float) );
C[i] = (float *)malloc( dg * sizeof(float) );
}
random_A_B(); /* rank为0的处理器随机化生成A、B矩阵*/
scatter_A_B(); /* rank为0的处理器向其他处理器发送A、B矩阵的相关块*/
} else /* rank不为0的处理器接收来自rank为0的处理器的相应矩阵分块*/
{
MPI_Recv(a, dl2, MPI_FLOAT, 0 , 1, MPI_COMM_WORLD, &status);
MPI_Recv(b, dl2, MPI_FLOAT, 0 , 2, MPI_COMM_WORLD, &status);
}
init_alignment(); /* A、B矩阵的初始对准*/
main_shift(); /* 分块矩阵左移、上移, cannon算法的主过程*/
if(my_rank == 0)
{
collect_C(); /* rank为0的处理器从其余处理器收集分块矩阵c */
print(A,"random matrix A : \n"); /* 打印矩阵A */
print(B,"random matrix B : \n"); /* 打印矩阵B */
print(C,"Matrix C = A * B : \n"); /* 打印矩阵C */
} else
{
MPI_Send(c,dl2,MPI_FLOAT,0,1,MPI_COMM_WORLD); /* rank不为0的处理器向rank为0的处理器发送矩阵块c */
}
MPI_Barrier(MPI_COMM_WORLD); /* 同步所有处理器*/
MPI_Finalize(); /* 结束MPI计算*/
return 0;
}
[文档可能无法思考全面,请浏览后下载,另外祝您生活愉快,工作顺利,万事如意!]。

相关文档
最新文档