以前沒接觸過MPI編程,對並行計算也沒什么了解。朋友的期末課程作業讓我幫忙寫一寫,哎,實現結果很一般啊。最終也沒完整完成任務,慚愧慚愧。
問題大概是利用MPI完成矩陣和向量相乘。輸入:Am×n,Bn×1 ,輸出:Cm×1
附:程序中定義m=400,n=100,矩陣和向量的取值為隨意整型數,為了便於顯示並行效果,循環完成該計算任務100000次。
實現過程
1.實驗環境:WINDOWS8.1 64位+ MPICH + VS2013 / kubuntu 14.04 + mpich
2.解題思路:采用帶狀划分的並行算法,同時用主從結構,設處理器個數為p,對矩陣A按行划分成p塊,每塊含有連續的m行向量,m = N/p,分別存放在標號0...p-1的處理器中,同時將向量B廣播給所有處理器。各處理器並行地進行矩陣向量乘積操作,最后返回結果。
運行代碼如下:
#include "mpi.h" #include <stdio.h> #include <stdlib.h> const int rows = 400; //the rows of matrix const int cols = 100; //the cols of matrix int main(int argc, char* argv[]) { int i, j, k, myid, numprocs, anstag; int A[rows][cols], B[cols], C[rows]; int masterpro,buf[cols], ans,cnt; double starttime,endtime; double tmp,totaltime; MPI_Status status; masterpro = 0; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &myid); MPI_Comm_size(MPI_COMM_WORLD, &numprocs); for(cnt = 0; cnt < 100000; cnt++){ if(numprocs < 2){ printf("Error:Too few processes!\n"); MPI_Abort(MPI_COMM_WORLD,99); } if(myid == masterpro){ starttime = MPI_Wtime(); for (i = 0; i < cols; i++) { B[i] = rand()%10; for (j = 0; j < rows; j++) { A[j][i] = rand()%10; } } //bcast the B vector to all slave processor MPI_Bcast(B, cols, MPI_INT, masterpro, MPI_COMM_WORLD); //partition the A matrix to all slave processor for (i = 1; i < numprocs; i++) { for (k = i - 1; k < rows; k += numprocs - 1) { for (j = 0; j < cols; j++) { buf[j] = A[k][j]; } MPI_Send(buf, cols, MPI_INT, i, k, MPI_COMM_WORLD); } } } else{ //starttime = MPI_Wtime(); MPI_Bcast(B, cols, MPI_INT, masterpro, MPI_COMM_WORLD); //every processor receive the part of A matrix,and make Mul operator with B vector for ( i = myid - 1; i < rows; i += numprocs - 1){ MPI_Recv(buf, cols, MPI_INT, masterpro, i, MPI_COMM_WORLD, &status); ans = 0; for ( j = 0; j < cols; j++) { ans += buf[j] * B[j]; } //send back the result MPI_Send(&ans, 1, MPI_INT, masterpro, i, MPI_COMM_WORLD); } //endtime = MPI_Wtime(); //tmp = endtime-starttime; } if(myid == masterpro){ //receive the result from all slave processor for ( i = 0; i < rows; i++) { MPI_Recv(&ans, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); //sender = status.MPI_SOURCE; anstag = status.MPI_TAG; C[anstag] = ans; } //print the result /* for (i = 0; i < rows; i++) { printf("%d ",C[i]); if((i+1)%20 == 0) printf("\n"); } */ } } endtime = MPI_Wtime(); totaltime = endtime-starttime; //printf("cost time:%f s.\n",tmp); //MPI_Reduce(&tmp,&totaltime,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD); if(myid == masterpro) printf("total time:%f s.\n",totaltime); MPI_Finalize(); return 0; }
測試結果:單機多進程運行時,由於進程資源分配和cpu使用率會隨着進程數增加而減少,所以時間反而會久一點。在linux上測試時,發現2進程運行時,CPU使用率能達100%,4進程運行時平均50%左右。
聯機測試過程,還存在一些問題,自己也沒處理好,這里就不誤導大家了。
環境搭建
Linux環境 kubuntu 14.04
(1)安裝:
sudo apt-get install mpd sudo apt-get install mpich
(2)編譯運行
mpicc -o matrixvec matrixvec.c mpirun -np 2 ./matrixvec
Windows環境
主要是MPICH3.1.3+VS2013搭建過程的一些注意問題。
(1)下載安裝:在MPICH官網下載相應的包,雖然系統是64位,但實際測試過程中,發現64為的mpich3.1.3無法運行,重新安裝32位版本后才正常,所以建議安裝32位版本。同時在環境變量PATH添加mpich/bin的路徑。
(2)注冊賬號:運行安裝目錄下的/bin/wmpiregister.exe,輸入系統用戶名、密碼。注意,這里注冊的是你在使用的電腦系統的用戶名和密碼。
(3)運行測試:運行安裝目錄下的/bin/wmpiexec.exe,選擇Application為安裝目錄下\examples\cpi.exe(一個計算圓周率的例子程序)
若遇到下例問題,用管理員權限打開控制台,輸入smpd -install即可
下面用VS2013實現簡單的mpi程序作為示例,分享一下配置過程。
(1)打開VS2013,新建項目及源文件
(2)配置項目屬性,引入mpi頭文件和庫
因為VC的IO庫與MPI頭文件中的宏定義有沖突,所以需要預定義一個MPICH_SKIP_MPICXX宏,使得預編譯時跳過MPICXX定義,同時可以添加_CRT_SECURE_NO_WARNINGS。
代碼生成,設置運行庫為多線程,在如下位置選擇“Multi-threaded Debug (/MTd)”,可以通過下拉單選擇
鏈接器添加連接庫,在如下位置添加“mpi.lib”
配置完成,通過VS編譯mpi程序,用wmpiexec.exe打開生成的exe文件便可運行,或者用命令行形式。
相關參考:
1.MoreWindows Blog:Windows系統下搭建MPI(並行計算)環境
2.Romi-知行合一:Windows下MPI的環境搭建及機群測試