MPI并行程序設(shè)計簡介_第1頁
MPI并行程序設(shè)計簡介_第2頁
MPI并行程序設(shè)計簡介_第3頁
MPI并行程序設(shè)計簡介_第4頁
MPI并行程序設(shè)計簡介_第5頁
已閱讀5頁,還剩48頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

MPI并行程序設(shè)計簡介曙光信息產(chǎn)業(yè)(北京)有限公司1講座內(nèi)容提示基本概念基本的MPI點(diǎn)到點(diǎn)通信(Pointtopoint)MPI中API的主要內(nèi)容,為MPI最基本,最重要的內(nèi)容MPI程序的編譯和運(yùn)行實例2參考文獻(xiàn)MPI--thecompletereference.MarcSnir,MITPress,1998.ISBN0262692155,0262692163.UsingMPI:portableparallelprogrammingwiththemessage-passinginterface,WilliamGropp,MITPress,1999.2ndedition.ISBN0262571323.UsingMPI-2:advancedfeaturesofthemessage-passinginterface.WilliamGropp,MITPress,1999.ISBN0262571331.高性能計算并行編程技術(shù)-MPI并行程序設(shè)計,都志輝,清華大學(xué)出版社,2001年8月。3多線程庫標(biāo)準(zhǔn)–Win32API.–POSIXthreads.編譯制導(dǎo)標(biāo)準(zhǔn)–OpenMP–可移植共享存儲并行編程標(biāo)準(zhǔn).消息傳遞庫標(biāo)準(zhǔn)–MPI

–PVM并行編程標(biāo)準(zhǔn)本討論的重點(diǎn)4消息傳遞并行程序設(shè)計消息傳遞并行程序設(shè)計指用戶必須通過顯式地發(fā)送和接收消息來實現(xiàn)處理機(jī)間的數(shù)據(jù)交換。在這種并行編程中,每個并行進(jìn)程均有自己獨(dú)立的地址空間,相互之間訪問不能直接進(jìn)行,必須通過顯式的消息傳遞來實現(xiàn)。這種編程方式是大規(guī)模并行處理機(jī)(MPP)和機(jī)群(Cluster)采用的主要編程方式。并行計算粒度大,特別適合于大規(guī)??蓴U(kuò)展并行算法由于消息傳遞程序設(shè)計要求用戶很好地分解問題,組織不同進(jìn)程間的數(shù)據(jù)交換,并行計算粒度大,特別適合于大規(guī)??蓴U(kuò)展并行算法.消息傳遞是當(dāng)前并行計算領(lǐng)域的一個非常重要的并行程序設(shè)計方式5什么是MPI?MassagePassingInterface:是消息傳遞函數(shù)庫的標(biāo)準(zhǔn)規(guī)范,由MPI論壇開發(fā),支持Fortran和C一種新的庫描述,不是一種語言。共有上百個函數(shù)調(diào)用接口,在Fortran和C語言中可以直接對這些函數(shù)進(jìn)行調(diào)用MPI是一種標(biāo)準(zhǔn)或規(guī)范的代表,而不是特指某一個對它的具體實現(xiàn)MPI是一種消息傳遞編程模型,并成為這種編程模型的代表和事實上的標(biāo)準(zhǔn)6MPI的發(fā)展過程發(fā)展的兩個階段MPI1.1:1995MPICH:是MPI最流行的非專利實現(xiàn),由Argonne國家實驗室和密西西比州立大學(xué)聯(lián)合開發(fā),具有更好的可移植性.MPI1.2~2.0:動態(tài)進(jìn)程,并行I/O,遠(yuǎn)程存儲訪問、支持F90和C++(1997).7為什么要用MPI?高可移植性MPI已在IBMPC機(jī)上、MSWindows上、所有主要的Unix工作站上和所有主流的并行機(jī)上得到實現(xiàn)。使用MPI作消息傳遞的C或Fortran并行程序可不加改變地運(yùn)行在IBMPC、MSWindows、Unix工作站、以及各種并行機(jī)上。8:從簡單入手

—Init和Finalize下面我們首先分別以C語言和Fortran語言的形式給出一個最簡單的MPI并行程序Hello(下頁).該程序在終端打印出HelloWorld!字樣.“HelloWorld”:一聲來自新生兒的問候.9Helloworld(C)#include<stdio.h>#include"mpi.h“main(

int

argc, char*argv[]){

MPI_Init(&argc,&argv);

printf("Hello,world!\n");

MPI_Finalize();}10Helloworld(Fortran)programmaininclude‘mpif.h’integerierrcallMPI_INIT(ierr)print*,'Hello,world!'callMPI_FINALIZE(ierr)end11C和Fortran中MPI函數(shù)約定C必須包含mpi.h.MPI函數(shù)返回出錯代碼或

MPI_SUCCESS成功標(biāo)志.MPI-前綴,且只有MPI以及MPI_標(biāo)志后的第一個字母大寫,其余小寫.Fortran必須包含mpif.h.通過子函數(shù)形式調(diào)用MPI,函數(shù)最后一個參數(shù)為返回值.MPI-前綴,且函數(shù)名全部為大寫.MPI函數(shù)的參數(shù)被標(biāo)志為以下三種類型:IN:參數(shù)在例程的調(diào)用中不會被修正.OUT:參數(shù)在例程的調(diào)用中可能會被修正.INOUT:參數(shù)有初始值,且在例程的調(diào)用中可能會被修正12MPI初始化-MPI_INITintMPI_Init(int*argc,char**argv)MPI_INIT(IERROR)MPI_INIT是MPI程序的第一個調(diào)用,它完成MPI程序的所有初始化工作。所有的MPI程序的第一條可執(zhí)行語句都是這條語句。啟動MPI環(huán)境,標(biāo)志并行代碼的開始.并行代碼之前,第一個mpi函數(shù)(除MPI_Initialized()外).要求main必須帶參數(shù)運(yùn)行,否則出錯.13MPI結(jié)束-MPI_FINALIZEintMPI_Finalize(void)MPI_FINALIZE(IERROR)MPI_FINALIZE是MPI程序的最后一個調(diào)用,它結(jié)束MPI程序的運(yùn)行,它是MPI程序的最后一條可執(zhí)行語句,否則程序的運(yùn)行結(jié)果是不可預(yù)知的。標(biāo)志并行代碼的結(jié)束,結(jié)束除主進(jìn)程外其它進(jìn)程.之后串行代碼仍可在主進(jìn)程(rank=0)上運(yùn)行(如果必須).14MPI程序的的編譯與運(yùn)行mpif77hello.f

或mpicc

hello.c

默認(rèn)生成a.out的可執(zhí)行代碼.mpif77–ohellohello.f

或mpicc–ohellohello.c生成hello的可執(zhí)行代碼.mpirun–np4a.outmpirun–np4hello4指定np的實參,表示進(jìn)程數(shù),由用戶指定.a.out/hello要運(yùn)行的MPI并行程序.%小寫onp:Thenumberofprocess.15:運(yùn)行我們的MPI程序![dair@node01~]$mpicc-ohellohello.c[dair@node01~]$./hello(

)[0]Abortingprogram!Couldnotcreatep4procgroup.Possiblemissingfileorprogramstartedwithoutmpirun.[dair@node01~]$

mpirun-np4hello

(

)HelloWorld!HelloWorld!HelloWorld!

HelloWorld![dair@node01~]$

計算機(jī)打印字符我們輸入的命令16

:Hello是如何被執(zhí)行的?SPMD:SingleProgramMultipleData(SIMD)

::::#include"mpi.h"#include<stdio.h>main(

int

argc,char*argv[]){

MPI_Init(&argc,&argv);

printf("Hello,world!\n");

MPI_Finalize();}#include"mpi.h"#include<stdio.h>main(

int

argc,char*argv[]){

MPI_Init(&argc,&argv);

printf("Hello,world!\n");

MPI_Finalize();}#include"mpi.h"#include<stdio.h>main(

int

argc,char*argv[]){

MPI_Init(&argc,&argv);

printf("Hello,world!\n");

MPI_Finalize();}#include"mpi.h"#include<stdio.h>main(

int

argc,char*argv[]){

MPI_Init(&argc,&argv);

printf("Hello,world!\n");

MPI_Finalize();}HelloWorld!HelloWorld!HelloWorld!HelloWorld!#include"mpi.h"#include<stdio.h>main(

int

argc,char*argv[]){

MPI_Init(&argc,&argv);

printf("Hello,world!\n");

MPI_Finalize();}rsh\ssh17:開始寫MPI并行程序

—Comm_size和Comm_rank在寫MPI程序時,我們常需要知道以下兩個問題的答案:任務(wù)由多少個進(jìn)程來進(jìn)行并行計算?我是哪一個進(jìn)程?

18MPI提供了下列函數(shù)來回答這些問題:用MPI_Comm_size

獲得進(jìn)程個數(shù)p

int

MPI_Comm_size(MPI_Comm

comm,int*size);用MPI_Comm_rank

獲得進(jìn)程的一個叫rank的值,該

rank值為0到p-1間的整數(shù),相當(dāng)于進(jìn)程的ID

int

MPI_Comm_rank(MPI_Comm

comm,int*rank);19更新的HelloWorld(c)#include<stdio.h>#include"mpi.h"main(intargc,char*argv[]){

intmyid,

numprocs;

MPI_Init(&argc,&argv);

MPI_Comm_rank(MPI_COMM_WORLD,&myid);

MPI_Comm_size(MPI_COMM_WORLD,&numprocs);printf(“Iam%dof%d\n",myid,numprocs);

MPI_Finalize();}20更新的HelloWorld(F77)programmaininclude‘mpif.h’integerierr,myid,numprocscallMPI_INIT(ierr)callMPI_COMM_RANK(MPI_COMM_WORLD,myid,ierr)callMPI_COMM_SIZE(MPI_COMM_WORLD,numprocs,ierr)print*,‘Iam',myid,‘of',numprocscallMPI_FINALIZE(ierr)end21

:運(yùn)行結(jié)果[dair@node01~]$mpicc–ohello1hello1.c[dair@node01~]$mpirun-np4hello1Iam0of4Iam1of4Iam2of4Iam3of4[dair@node01~]$計算機(jī)打印字符我們輸入的命令22:寫MPI并行通信程序

--Send和RecvGreeting執(zhí)行過程23有消息傳遞greetings(c)#include<stdio.h>#include"mpi.h"main(int

argc,char*argv[]){

int

numprocs,myid,source;

MPI_Statusstatus;charmessage[100];

MPI_Init(&argc,&argv);

MPI_Comm_rank(MPI_COMM_WORLD,&myid);

MPI_Comm_size(MPI_COMM_WORLD,&numprocs);24有消息傳遞greetings(c)if(myid!=0){

strcpy(message,"HelloWorld!");

MPI_Send(message,strlen(message)+1,MPI_CHAR,0,99,MPI_COMM_WORLD);}else{/*myid==0*/for(source=1;source<numprocs;source++){

MPI_Recv(message,100,MPI_CHAR,source,99,MPI_COMM_WORLD,&status);

printf("%s\n",message);}}

MPI_Finalize();}/*endmain*/25解剖greetings程序頭文件:mpi.h/mpif.h.int

MPI_Init(int*argc,char***argv)啟動MPI環(huán)境,標(biāo)志并行代碼的開始.并行代碼之前,第一個mpi函數(shù)(除MPI_Initialize()外).要求main必須帶參數(shù)運(yùn)行,否則出錯.通信域(通信空間):MPI_COMM_WORLD:一個通信空間是一個進(jìn)程組和一個上下文的組合.上下文可看作為組的超級標(biāo)簽,用于區(qū)分不同的通信域.在執(zhí)行函數(shù)MPI_Init之后,一個MPI程序的所有進(jìn)程形成一個缺省的組,這個組的通信域即被寫作MPI_COMM_WORLD.該參數(shù)是MPI通信操作函數(shù)中必不可少的參數(shù),用于限定參加通信的進(jìn)程的范圍.26解剖greetings程序int

MPI_Comm_size(MPI_Comm

comm,int*size)獲得通信空間comm中規(guī)定的組包含的進(jìn)程的數(shù)量.指定一個communicator,也指定了一組共享該空間的進(jìn)程,這些進(jìn)程組成該communicator的group.int

MPI_Comm_rank(MPI_Comm

comm,int*rank)得到本進(jìn)程在通信空間中的rank值,即在組中的邏輯編號(從0開始).int

MPI_Finalize()標(biāo)志并行代碼的結(jié)束,結(jié)束除主進(jìn)程外其它進(jìn)程.之后串行代碼仍可在主進(jìn)程(rank=0)上運(yùn)行(如果必須).27講座內(nèi)容提示基本的MPI基本概念點(diǎn)到點(diǎn)通信(Pointtopoint)MPI中API的主要內(nèi)容,為MPI最基本,最重要的內(nèi)容MPI程序的編譯和運(yùn)行深入MPI用戶自定義(/派生)數(shù)據(jù)類型(User-defined(Derived)datatype)事實上MPI的所有數(shù)據(jù)類型均為MPI自定義類型支持異構(gòu)系統(tǒng)允許消息來自不連續(xù)的或類型不一致的存儲區(qū)(結(jié)構(gòu),數(shù)組散元)集合通信(Collective)數(shù)據(jù)移動,數(shù)據(jù)聚集,同步基于pointtopoint構(gòu)建MPI環(huán)境管理函數(shù)組,上下文和通信空間/通信域的管理實例28PointtoPoint通信單個進(jìn)程對單個進(jìn)程的通信,重要且復(fù)雜術(shù)語Blocking(阻塞):一個例程須等待操作完成才返回,返回后用戶可以重新使用調(diào)用中所占用的資源.

Non-blocking(非阻塞):一個例程不必等待操作完成便可返回,但這并不意味著所占用的資源可被重用.

Local(本地):過程的完成僅依賴于本地正在執(zhí)行的進(jìn)程。Non-local(非本地):如果過程的完成要求其他進(jìn)程的MPI過程完成。29BlockingSendintMPI_Send(void*buf,intcount,MPI_Datatypedatatype,intdest,inttag,MPI_Commcomm);

INbuf 發(fā)送緩沖區(qū)的起始地址

INcount 要發(fā)送信息的元素個數(shù)

INdatatype發(fā)送信息的數(shù)據(jù)類型

INdest 目標(biāo)進(jìn)程的rank值

INtag 消息標(biāo)簽

INcomm 通信域30BlockingReceiveintMPI_Recv(void*buf,intcount,MPI_Datatypedatatype,intsource,inttag,MPI_Commcomm,MPI_Status*status);

OUTbuf 發(fā)送緩沖區(qū)的起始地址

INcount 要發(fā)送信息的元素個數(shù)

INdatatype 發(fā)送信息的數(shù)據(jù)類型

INdest 目標(biāo)進(jìn)程的rank值

INtag 消息標(biāo)簽

INcomm 通信域

OUTstatus status對象,包含實際接收到的消息的有關(guān)信息31MPI消息MPI消息包括信封和數(shù)據(jù)兩個部分,信封指出了發(fā)送或接收消息的對象及相關(guān)信息,而數(shù)據(jù)是本消息將要傳遞的內(nèi)容數(shù)據(jù):<起始地址、數(shù)據(jù)個數(shù)、數(shù)據(jù)類型>信封:<源/目的、標(biāo)識、通信域>3233消息數(shù)據(jù)由count個類型為datatype的連續(xù)數(shù)據(jù)空間組成,起始地址為buf不是以字節(jié)數(shù),而是以元素的個數(shù)指定消息的長度count可以是零,這種情況下消息的數(shù)據(jù)部分是空的MPI基本數(shù)據(jù)類型相應(yīng)于宿主語言的基本數(shù)據(jù)類型34MPI基本數(shù)據(jù)類型35MPI標(biāo)識一條消息的信息包含四個域:Source:發(fā)送進(jìn)程隱式確定,由進(jìn)程的rank值唯一標(biāo)識Destination:Send函數(shù)參數(shù)確定Tag:Send函數(shù)參數(shù)確定,用于識別不同的消息

(0,UB),UB:MPI_TAG_UB>=32767.Communicator:缺省MPI_COMM_WORLDGroup:有限/N,有序/Rank[0,1,2,…N-1]Contex:Super_tag,用于標(biāo)識該通訊空間.消息信封36status參數(shù)當(dāng)使用MPI_ANY_SOURCE或/和MPI_ANY_TAG接收消息時如何確定消息的來源source和tag值呢?在C中,結(jié)構(gòu),status.MPI_SOURCE,status.MPI_TAG.在Fortran中,數(shù)組,source=status(MPI_SOURCE),tag=status(MPI_TAG).Status還可用于返回實際接收到消息的長度int

MPI_Get_count(MPI_Statusstatus,MPI_Datatype

datatype,int*count)INstatus接收操作的返回值.INdatatype

接收緩沖區(qū)中元素的數(shù)據(jù)類型.OUTcount接收消息中的元素個數(shù).37消息匹配接收buffer必須至少可以容納count個由datatype參數(shù)指明類型的數(shù)據(jù).如果接收buf太小,將導(dǎo)致溢出、出錯.消息匹配參數(shù)匹配dest,tag,comm/source,tag,commSource==MPI_ANY_SOURCE:接收任意處理器來的數(shù)據(jù)(任意消息來源).Tag==MPI_ANY_TAG:匹配任意tag值的消息(任意tag消息).Source=destination是允許的,但是不安全的,可能導(dǎo)致死鎖。消息傳送被限制在同一個communicator.在send函數(shù)中必須指定唯一的接收者(Push/pull通訊機(jī)制).38分析greetings#include<stdio.h>#include"mpi.h“main(int

argc,char*argv[]){

int

numprocs;/*進(jìn)程數(shù),該變量為各處理器中的同名變量,存儲是分布的 */

int

myid; /*我的進(jìn)程ID,存儲也是分布的 */

MPI_Statusstatus; /*消息接收狀態(tài)變量,存儲也是分布的 */

charmessage[100]; /*消息buffer,存儲也是分布的 */

/*初始化MPI*/

MPI_Init(&argc,&argv);/*該函數(shù)被各進(jìn)程各調(diào)用一次,得到自己的進(jìn)程rank值*/

MPI_Comm_rank(MPI_COMM_WORLD,&myid);

/*該函數(shù)被各進(jìn)程各調(diào)用一次,得到進(jìn)程數(shù)*/

MPI_Comm_size(MPI_COMM_WORLD,&numprocs);39分析greetingsif(myid!=0){

/*建立消息*/

sprintf(message,"Greetingsfromprocess%d!",myid);

/*發(fā)送長度取strlen(message)+1,使\0也一同發(fā)送出去*/

MPI_Send(message,strlen(message)+1,MPI_CHAR,0,99,MPI_COMM_WORLD);}else{/*my_rank==0*/for(source=1;source<numprocs;source++){

MPI_Recv(message,100,MPI_CHAR,source,99,MPI_COMM_WORLD,&status);

printf(“%s\n",message);}}

/*關(guān)閉MPI,標(biāo)志并行代碼段的結(jié)束*/

MPI_Finalize();}/*Endmain*/40Greetings執(zhí)行過程假設(shè)進(jìn)程數(shù)為3(進(jìn)程0)(進(jìn)程1)(進(jìn)程2)(rank=0)(rank=1)(rank=2)..Recv();..Recv();.....Send();......Send()...問題:進(jìn)程1和2誰先開始發(fā)送消息?誰先完成發(fā)送??%41運(yùn)行g(shù)reetings[dair@node01~]$mpicc–ogreetinggreeting.c[dair@node01~]$mpirun-np4greetingGreetingsfromprocess1!Greetingsfromprocess2!Greetingsfromprocess3![dair@node01~]$計算機(jī)打印字符我們輸入的命令42最基本的MPIMPI調(diào)用借口的總數(shù)雖然龐大,但根據(jù)實際編寫MPI的經(jīng)驗,常用的MPI調(diào)用的個數(shù)非常有限。上面介紹的是6個最基本的MPI函數(shù)。MPI_Init(…);MPI_Comm_size(…);MPI_Comm_rank(…);MPI_Send(…);MPI_Recv(…);MPI_Finalize();MPI_Init(…);…并行代碼;…MPI_Fainalize();只能有串行代碼;43現(xiàn)在您已經(jīng)能夠用MPI進(jìn)行并行編程了!44實例分析:求PI45串行代碼h=1.0/(double)n;sum=0.0;for(i=1;i<=n;i++){ x=h*((double)i–0.5); sum+=f(x);}pi=h*sum;doublef(doublea){ return(4.0/(1.0+a*a));}46并行代碼h=1.0/(double)n;sum=0.0;for(i=myid+1;i<=n;i+=numprocs){ x=h*((double)i–0.5); sum+=f(x);}mypi=h*sum;

MPI_Reduce(&mypi,&pi,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);doublef(doublea){ return(4.0/(1.0+a*a));}47cpi.c#include"mpi.h"#include<stdio.h>#include<math.h>doublef(double);doublef(doublea);{return(4.0/(1.0+a*a));}48cpi.cintmain(int

argc,char*argv[]){intdone=0,n,myid,numprocs,i;doublePI25DT=3.141592653589793238462643;doublemypi,pi,h,sum,x;

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論