智障大學一附院精神科主任醫師胡老師
阿新 • • 發佈:2018-12-15
學習筆記-矩陣乘的MPI實現
目前還是萌新,看了兩天書,自己硬著頭皮寫出來了。主要思想是書中介紹的,主程序將矩陣A的各行依此傳送給從程序,從程序計算該行與矩陣B的相乘結果,並向主程序傳送這一結果。
#include<stdio.h> #include"mpi.h" #define A_ROW 500 #define A_CLO_B_ROW 600 #define B_CLO 700 #define SHUT_DOWN_TAG -1 int main(void) { //初始化 int mat1[A_ROW][A_CLO_B_ROW]; int mat2[A_CLO_B_ROW][B_CLO]; for(int i=0;i<A_CLO_B_ROW;i++) { for(int j=0;j<A_ROW;j++){ //mat1[j][i]=j*10+i; mat1[j][i]=1; } for(int k=0;k<B_CLO;k++){ //mat2[i][k]=i*10+k; mat2[i][k]=1; } } //result int res[A_ROW][B_CLO]; //記時 double start_time,end_time; double m_time; //並行 int l,m,n,send_row; int task_num; int rank,size; MPI_Status status; int vec1[B_CLO]; int vec2[A_CLO_B_ROW]; MPI_Init(NULL,NULL); start_time=MPI_Wtime(); MPI_Comm_rank(MPI_COMM_WORLD,&rank); MPI_Comm_size(MPI_COMM_WORLD,&size); task_num=(A_ROW+size-2)/(size-1);//向上取整 for(l=0;l<task_num;l++)//傳送接收task_num輪 { if(rank==0)//主程序 { for(m=0;m<size-1;m++)//傳送給剩下size-1個程序 { send_row=m+l*(size-1);//計算髮送矩陣1的行號(0~A_ROW-1) if(send_row<A_ROW)//行號小於矩陣1的行數 { for(int o=0;o<A_CLO_B_ROW;o++){ vec2[o]=mat1[send_row][o];//該行資料放入緩衝區vect中 } MPI_Send(vec2,A_CLO_B_ROW,MPI_INT,m+1,send_row,MPI_COMM_WORLD);//傳送給對應的程序 //printf("master has send %d row to process %d \n",send_row,m+1); }//本輪發送結束 } //開始本輪接收 for(int rec=0;rec<size-1;rec++){ MPI_Recv(vec1,B_CLO,MPI_INT,MPI_ANY_SOURCE,rec+l*(size-1),MPI_COMM_WORLD,&status);//接收對應行號的結果 //printf("master has receive res %d row from %d process\n",rec+l*(size-1),status.MPI_SOURCE); for(int s=0;s<B_CLO;s++)//存放到結果矩陣中 { res[status.MPI_TAG][s]=vec1[s]; } if(status.MPI_TAG==A_ROW-1){//結束 end_time=MPI_Wtime(); m_time=end_time-start_time; printf("%d !\n",res[0][0]); printf("time:%f s \n",m_time); printf("speed_up= %f for %d process!\n",c_time/m_time,size); MPI_Abort(MPI_COMM_WORLD,99); } } } else//其餘程序 { MPI_Recv(vec2,A_CLO_B_ROW,MPI_INT,0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);//接收自己的資料 if(status.MPI_TAG==SHUT_DOWN_TAG){ MPI_Barrier(MPI_COMM_WORLD); printf("process exit!",rank); } else{ //printf("process %d has recieve %d row!\n",rank,status.MPI_TAG); for(int p=0;p<B_CLO;p++){ int elem=0; for(int r=0;r<A_CLO_B_ROW;r++){ elem+=vec2[r]*mat2[r][p]; } vec1[p]=elem; }//橫向量寫入到vec MPI_Send(vec1,B_CLO,MPI_INT,0,rank+l*(size-1)-1,MPI_COMM_WORLD);//傳送 //printf("process has send %d\n",rank+l*(size-1)-1); } } } MPI_Finalize(); }