MPI 加農算法計算矩陣相乘 為了實現方便 只實現了矩陣自乘 而且 實際上各線程都可讀取整個矩陣(略去輸入和分配中的通信過程)
在各線程相互交換數據的過程中 一定要注意避免死鎖
- #include "mpi.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
-
- #define TAG 0
-
- static inline void rtoij(int r,int w,int *i,int *j) {
- //rank to i,j
- *i=r/w;
- *j=r-(*i)*w;
- }
- static inline void ijtor(int i,int j,int *r,int w) {
- //i,j to rank
- *r=i*w+j;
- }
- static inline int aj(int i,int j,int w) {
- return (j+i)%w;
- }
- static inline int bi(int i,int j,int w) {
- //initial b distribute
- return aj(i,j,w);
- }
- int main(int argc,char *argv[]) {
- float m[][2]={{1,2},
- {3,4}};//the matrix
- //multiply by itself
- int self,size;
- MPI_Init(&argc,&argv);
- MPI_Comm_rank(MPI_COMM_WORLD,&self);
- MPI_Comm_size(MPI_COMM_WORLD,&size);
- MPI_Request r;
- MPI_Status s;
- int w=sqrt(size);
- int i,j,an,bn,ap,bp;
- rtoij(self,w,&i,&j);
- ijtor(i,(j+w-1)%w,&an,w);//next a process
- ijtor((i+w-1)%w,j,&bn,w);//next b process
- ijtor(i,(j+1)%w,&ap,w);//previous a process
- ijtor((i+1)%w,j,&bp,w);
-
- float res,a,b,tmp;
- //initialize data distribution
- a=m[i][aj(i,j,w)];
- b=m[bi(i,j,w)][j];
- res=a*b;
-
- for(int i=0;i<w-1;++i) {
- MPI_Issend(&a,1,MPI_FLOAT,an,TAG,MPI_COMM_WORLD,&r);//avoid dead lock
- MPI_Recv(&tmp,1,MPI_FLOAT,ap,TAG,MPI_COMM_WORLD,&s);
- a=tmp;
- MPI_Wait(&r,&s);
-
- MPI_Issend(&b,1,MPI_FLOAT,bn,TAG,MPI_COMM_WORLD,&r);//avoid dead lock
- MPI_Recv(&tmp,1,MPI_FLOAT,bp,TAG,MPI_COMM_WORLD,&s);
- b=tmp;
- MPI_Wait(&r,&s);
-
- res+=a*b;
- }
- if(0==self) {
- printf("%f",res);
- for(int i=1;i<size;++i) {
- MPI_Recv(&res,1,MPI_FLOAT,i,TAG,MPI_COMM_WORLD,&s);
- printf(" %f",res);
- }
- printf("\n");
- } else {
- MPI_Ssend(&res,1,MPI_FLOAT,0,TAG,MPI_COMM_WORLD);
- }
- MPI_Finalize();
- return 0;
- }