裝置OpenMPI來合營C說話法式停止並行盤算。本站提示廣大學習愛好者:(裝置OpenMPI來合營C說話法式停止並行盤算)文章只能為提供參考,不一定能成為您想要的結果。以下是裝置OpenMPI來合營C說話法式停止並行盤算正文
裝置OPENMPI
因為是試驗,也不停止多機的設置裝備擺設了,只在虛擬機裡裝置吧。多個機械的設置裝備擺設可以參考此文
最簡略的辦法,apt裝置
sudo apt-get install libcr-dev mpich2 mpich2-doc
測試
hello.c
/* C Example */
#include <mpi.h>
#include <stdio.h>
int main (int argc, char* argv[])
{
int rank, size;
MPI_Init (&argc, &argv); /* starts MPI */
MPI_Comm_rank (MPI_COMM_WORLD, &rank); /* get current process id */
MPI_Comm_size (MPI_COMM_WORLD, &size); /* get number of processes */
printf( "Hello world from process %d of %d\n", rank, size );
MPI_Finalize();
return 0;
}
編譯運轉及顯示成果
mpicc mpi_hello.c -o hello mpirun -np 2 ./hello Hello world from process 0 of 2 Hello world from process 1 of 2
正常湧現成果注解沒有成績,
看下openmpi的版本
mpirun --version
mpirun (Open MPI) 1.6.5 Report bugs to http://www.open-mpi.org/community/help/
MPI盤算矩陣乘法
經由過程opemMPI加快矩陣乘法運算。采取主從形式,0號是master,其他是child(或許叫worker,as you wish)。
根本思緒
兩個矩陣A,B停止乘法運算,則A的行 i 乘以B的列 j 得出的數是新矩陣(i,j)坐標的數值。A(MN) B(NK)最初矩陣是M*K的,試驗中M=N=K=1000,我也就沒有明白辨別MNK,全體用MATRIX_SIZE界說的。
最簡略的思緒就是每一個worker分派(MATRIX_SIZE/(numprocess-1))個,然後假如不足下的,就分給余數對應的worker。好比MATRIX_SIZE=10,numprocess=4 則現實的worker有3個,每一個人分3行,最初的一行給id是1的。可以很簡略的應用輪回類分派。最初Master搜集一切的成果,並依照次序組裝起來就行。
每一個worker的任務就是吸收來自master的一行,和B矩陣運算,得出新一行的成果,然後發送回master
代碼
多加了許多正文來說明,函數的解釋下一節說明下。
#include <mpi.h>
#include <stdio.h>
#define MATRIX_SIZE 10
#define FROM_MASTER 1 //這裡的類型可以辨別新聞的品種,以便辨別worker發送來的成果
#define FROM_CHILD 2
#define MASTER 0
MPI_Status status;
int myid,numprocess;
//終究保留的成果
int ans [MATRIX_SIZE*MATRIX_SIZE];
int A[MATRIX_SIZE*MATRIX_SIZE],B[MATRIX_SIZE*MATRIX_SIZE];
//讀取文件,留意讀取文件要放在master裡,否則會讀兩遍,湧現毛病
void readFile(){
FILE* fina,*finb;
fina=fopen("a.txt","r");
int i;
for (i = 0; i < MATRIX_SIZE*MATRIX_SIZE ; ++i)
{
fscanf(fina,"%d ",&A[i]);
}
fclose(fina);
finb=fopen("b.txt","r");
for(i=0;i<MATRIX_SIZE*MATRIX_SIZE;i++)
fscanf(finb,"%d ",&B[i]);
fclose(finb);
printf("read file ok\n");
}
int master(){
int workid,dest,i,j;
printf("numprocess %d\n",numprocess );
//給每一個worker發送B矩陣曩昔
for(i=0;i<numprocess-1;i++){
//send B matrix
MPI_Send(&B,MATRIX_SIZE*MATRIX_SIZE,MPI_INT,i+1,FROM_MASTER,MPI_COMM_WORLD);
}
//開端給每一個worker分派義務,取模便可
for (i = 0; i < MATRIX_SIZE; i++)
{
//attention: num of workers is numprocess-1
workid=i%(numprocess-1)+1;
//send single line in A
MPI_Send(&A[i*MATRIX_SIZE],MATRIX_SIZE,MPI_INT,workid,FROM_MASTER,MPI_COMM_WORLD);
}
//期待從worker發送來的數據
int tempLine[MATRIX_SIZE];
for (i = 0; i < MATRIX_SIZE*MATRIX_SIZE; i++)
{
ans[i]=0;
}
for (i = 0; i < MATRIX_SIZE; ++i)
{
int myprocess=i%(numprocess-1)+1;
printf("Master is waiting %d\n",myprocess);
//receive every line from every process
MPI_Recv(&tempLine,MATRIX_SIZE,MPI_INT,myprocess,FROM_CHILD,MPI_COMM_WORLD,&status);
//發送過去的都是盤算好了的一行的數據,直接組裝到ans裡就行
for(j=0;j<MATRIX_SIZE;j++){
ans[MATRIX_SIZE*i+j]=tempLine[j];
}
printf("Master gets %d\n",i);
}
for(i=0;i<MATRIX_SIZE*MATRIX_SIZE;i++){
printf("%d ",ans[i] );
if(i%MATRIX_SIZE==(MATRIX_SIZE-1))printf("\n");
}
printf("The Master is out\n");
}
int worker(){
int mA[MATRIX_SIZE],mB[MATRIX_SIZE*MATRIX_SIZE],mC[MATRIX_SIZE];
int i,j,bi;
MPI_Recv(&mB,MATRIX_SIZE*MATRIX_SIZE,MPI_INT,MASTER,FROM_MASTER,MPI_COMM_WORLD,&status);
//吸收來自master的A的行
for(i=0;i<MATRIX_SIZE/(numprocess-1);i++){
MPI_Recv(&mA,MATRIX_SIZE,MPI_INT,MASTER,FROM_MASTER,MPI_COMM_WORLD,&status);
//矩陣乘法,A 的一行和B矩陣相乘
for(bi=0;bi<MATRIX_SIZE;bi++){
mC[bi]=0;
for(j=0;j<MATRIX_SIZE;j++){
mC[bi]+=mA[j]*mB[bi*MATRIX_SIZE+j];
}
}
MPI_Send(&mC,MATRIX_SIZE,MPI_INT,MASTER,FROM_CHILD,MPI_COMM_WORLD);
}
//假如處於余數規模內,則須要多盤算一行
if(MATRIX_SIZE%(numprocess-1)!=0){
if (myid<=(MATRIX_SIZE%(numprocess-1)))
{
MPI_Recv(&mA,MATRIX_SIZE,MPI_INT,MASTER,FROM_MASTER,MPI_COMM_WORLD,&status);
for(bi=0;bi<MATRIX_SIZE;bi++){
mC[bi]=0;
for(j=0;j<MATRIX_SIZE;j++){
mC[bi]+=mA[j]*mB[bi*MATRIX_SIZE+j];
}
}
MPI_Send(&mC,MATRIX_SIZE,MPI_INT,MASTER,FROM_CHILD,MPI_COMM_WORLD);
}
}
printf("The worker %d is out\n",myid);
}
int main(int argc, char **argv)
{
MPI_Init (&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
MPI_Comm_size(MPI_COMM_WORLD,&numprocess);
if(myid==MASTER){
readFile();
master();
}
if(myid>MASTER){
worker();
}
MPI_Finalize();
return 0;
}
OPENMPI簡略函數引見
針對試驗用到的幾個函數停止解釋。
MPI為法式員供給一個並行情況庫,法式員經由過程挪用MPI的庫法式來到達法式員所要到達的並行目標,可以只應用個中的6個最根本的函數就可以編寫一個完全的MPI法式去求解許多成績。這6個根本函數,包含啟動和停止MPI情況,辨認過程和發送和吸收新聞:
實際上說,MPI一切的通訊功效可以用它的六個根本的挪用來完成:
初始化和停止
MPI初始化:經由過程MPI_Init函數進入MPI情況並完成一切的初始化任務。
int MPI_Init( int *argc, char * * * argv )
MPI停止:經由過程MPI_Finalize函數從MPI情況中加入。
int MPI_Finalize(void)
獲得過程的編號
挪用MPI_Comm_rank函數取得以後過程在指定通訊域中的編號,將本身與其他法式辨別。
int MPI_Comm_rank(MPI_Comm comm, int *rank)
獲得指定通訊域的過程數
挪用MPI_Comm_size函數獲得指定通訊域的過程個數,肯定本身完成義務比例。
int MPI_Comm_size(MPI_Comm comm, int *size)
MPI新聞
一個新聞比如一封信
新聞的內容的內容即信的內容,在MPI中成為新聞緩沖(Message Buffer)
新聞的吸收發送者即信的地址,在MPI中成為新聞封裝(Message Envelop)
MPI中,新聞緩沖由三元組<肇端地址,數據個數,數據類型>標識
新聞信封由三元組<源/目的過程,新聞標簽,通訊域>標識
新聞發送
MPI_Send函數用於發送一個新聞到目的過程。
int MPI_Send(void *buf, int count, MPI_Datatype dataytpe, int dest, int tag, MPI_Comm comm)
buf是要發送數據的指針,好比一個A數組,可以直接&A,count則是數據長度,datatype都要改成MPI的type。dest就是worker的id了。tag則可以經由過程分歧的type來辨別新聞類型,好比是master發送的照樣worker發送的。
新聞吸收
MPI_Recv函數用於從指定過程吸收一個新聞
int MPI_Recv(void *buf, int count, MPI_Datatype datatyepe,int source, int tag, MPI_Comm comm, MPI_Status *status)
編譯和履行
生成履行文件data
mpicc -o programname programname.c
一個MPI並行法式由若干個並發過程構成,這些過程可以雷同也能夠分歧。MPI只支撐靜態過程創立,即:每一個過程在履行前必需在MPI情況中掛號,且它們必需一路啟動。平日啟動可履行的MPI法式是經由過程敕令行來完成的。啟動辦法由詳細完成肯定。例如在MPICH完成中經由過程以下敕令行可同時在自力的機械上啟動雷同的可履行法式:
mpirun –np N programname
個中N是同時運轉的過程的個數,programname是可履行的MPI法式的法式名。