《分布内存并行程序开发》由会员分享,可在线阅读,更多相关《分布内存并行程序开发(44页珍藏版)》请在金锄头文库上搜索。
1、卉镐秦潘殃哼涯汁丸洗译纶具步那吼戮诸脾叙紧秉绵亩羚腑皆窍顿仅亩杖分布内存并行程序开发分布内存并行程序开发MPI分布内存并行分布内存并行程序开发程序开发夫脓剁雷积跳驮第雷薛惧礼蜕讣磋同敢澡藉曰沂这设洪休虐越程锣藉奴卵分布内存并行程序开发分布内存并行程序开发 第一章第一章并行计算概述并行计算概述旦药蚁釉邮山庆赁施浆幽梅藻躬屈册早襟皿摧犀官某叠逾阎扫社熔冬宏嘱分布内存并行程序开发分布内存并行程序开发2 2 为什麽要采用并行计算为什麽要采用并行计算?串行程序速度提升缓慢可以加快速度更短的时间内解决相同的问题;相同的时间内解决更多更复杂的问题可以加大规模计算更大规模的问题圈吐朵隆篡雀慕啪门毒馏呵败参兄靡
2、咳陇柳娩尸惶至贮掂爽悲腻峡狙庶赣分布内存并行程序开发分布内存并行程序开发3 3 并行计算设计的分类并行计算设计的分类 共享内存ccNUMA; SMP 分布式内存MPP; ClusterMPP; Cluster貌靳溅胸葱沟接芒美鸯到驾磕样逼淌沿沁濒刃挺龚缔杠惯六练匠鱼披隔陪分布内存并行程序开发分布内存并行程序开发4 4 三种计算模型三种计算模型驾教沼霄皿梨指避项陕瘩据麻必林郝百忱峨汀万睛窗惠连蹬迟忍会桩某馒分布内存并行程序开发分布内存并行程序开发5 5 并行化分解方法并行化分解方法任务分解多任务并发执行功能分解分解被执行的计算区域分解分解被执行的数据响挎猪鬃炭波驳溺洞四珠柏号峡捷拣挠豢和松孙斧斗
3、掂冯玄钒微想米鞭酣分布内存并行程序开发分布内存并行程序开发6 6 分布内存并行方式分布内存并行方式任务并行任务并行不同参数的大量工况计算不同参数的大量工况计算不同参数的大量工况计算不同参数的大量工况计算区域分解并行区域分解并行大规模多节点分块并行计算大规模多节点分块并行计算大规模多节点分块并行计算大规模多节点分块并行计算暗埔员冕殴汰捧粒邯嫡呀事匣磐砖浚飘躇粟微极馒论卖舅进陪逛拼洼伞耸分布内存并行程序开发分布内存并行程序开发7 7第二章第二章 MPIMPI简介简介MPI(Message Passing Interface )是1994年5月发布的一种消息传递接口。它实际上是一个消息传递函数库的标
4、准说明,以语言独立的形式来定义这个接口库, 并提供了与C和Fortran语言的绑定.。 棺痰膳亨收拂镶庚端猛钢个浪晦莱舞灼搂菠等倔穆床髓铝脓三秽倦媳弛禾分布内存并行程序开发分布内存并行程序开发8 8 MPIMPI的历史的历史MPI初稿:美国并行计算中心工作会议(92年4月)MPI-1公布:第一届MPI大会(93年1月);MPI标准正式发布:1994年5月;MPI-2发布:MPI论坛(97年)。猩章弓窄姬戳拆戏斡乏梳叠店烁国艰去漆箍睦廊握愈纫滓乐链鞋基固拎用分布内存并行程序开发分布内存并行程序开发9 9MPICH:最重要的MPI实现(www-unix.mcs.anl.gov/mpi/ mpich
5、),与MPI-1规范同步发展的版本,支持部分MPI-2的特征如动态生成进程等。CHIMP:EPCC(Edinburgh Parallel Computing Center)开发。ftp:/ftp.epcc.ed.ac.uk/pub/packages/chimp/release下载。LAM(Local Area Multicomputer):Ohio State University开发。http:/www.lam-mpi.org/download/下载。 MPI的实现土廷滑兹梆史兆幢繁衡盆寂股拷肠渝排杏肛贵汽咆谱蜂靴还莱旋甭像外钧分布内存并行程序开发分布内存并行程序开发1010 第三章第三章
6、MPIMPI编程编程葵匡抡鹅邹介掉体欠阁迪别簇厚听俊犊冈屑爬钮曲误卿允泞譬象栽舔唤楚分布内存并行程序开发分布内存并行程序开发1111 MPI为程序员提供一个并行环境库,程序员通过调用为程序员提供一个并行环境库,程序员通过调用MPIMPI的库的库程序来达到程序员所要达到的并行目的,可以只使用其中的程序来达到程序员所要达到的并行目的,可以只使用其中的6个最基本的函数就能编写一个完整的个最基本的函数就能编写一个完整的MPI程序去求解很多问题。程序去求解很多问题。这这6个基本函数,包括启动和结束个基本函数,包括启动和结束MPI环境,识别进程以及发环境,识别进程以及发送和接收消息:送和接收消息:MPI_
7、INIT: MPI_INIT: MPI_INIT: MPI_INIT: 启动启动启动启动MPIMPIMPIMPI环境环境环境环境MPI_COMM_SIZE: MPI_COMM_SIZE: MPI_COMM_SIZE: MPI_COMM_SIZE: 确定进程数确定进程数确定进程数确定进程数MPI_COMM_RANK: MPI_COMM_RANK: MPI_COMM_RANK: MPI_COMM_RANK: 确定自己的进程标识符确定自己的进程标识符确定自己的进程标识符确定自己的进程标识符MPI_SEND: MPI_SEND: MPI_SEND: MPI_SEND: 发送一条消息发送一条消息发送一条
8、消息发送一条消息MPI_RECV: MPI_RECV: MPI_RECV: MPI_RECV: 接收一条消息接收一条消息接收一条消息接收一条消息MPI_FINALIZE: MPI_FINALIZE: MPI_FINALIZE: MPI_FINALIZE: 结束结束结束结束MPIMPIMPIMPI环境环境环境环境征逃巫重漳底稿堰惯陇诬祭骑鸟忻雕茸绍肄指翅讥卜渭墨骚缚肪饶主倡现分布内存并行程序开发分布内存并行程序开发1212 程序程序1、 简单例子简单例子 program maininclude mpif.h character * (MPI_MAX_PROCESSOR_NAME) process
9、or_nameinteger myid,numprocs,namelen,rc,ierr call MPI_INIT(ierr)call MPI_COMM_RANK(MPI_COMM_WORLD,myid,ierr)call MPI_COMM_SIZE(MPI_COMM_WORLD,numprocs,ierr)call MPI_GET_PROCESSOR_NAME(processor_name,namelen,ierr)write (*,10) myid,numprocs,processor_name10 FORMAT(Hello World! Process,I2, of ,I1, on ,
10、20A)call MPI_FINALIZE(rc) end朴宇哈醒氟骋玻逗保穗优撇胎宅批梆凸森粘挎岳蛀晕风肪财缚桨走床测锥分布内存并行程序开发分布内存并行程序开发1313 程序程序1、 简单例子简单例子#include “mpi.h”main(int argc, char *argv) int numprocs,myrank,i,j,k; MPI_Status status; char msg20; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&numprocs); MPI_Comm_rank(MPI_COMM_WORLD,&myra
11、nk); if(myrank = 0) strcpy(msg,”Hello World”); MPI_Send(msg,strlen(msg) + 1,MPI_CHAR,1,99,MPI_COMM_WORLD); else if(myrank =1) MPI_Recv(msg,20,MPI_CHAR,0,99,MPI_COMM_WORLD,&status); printf(“Receive message = %sn”,msg); MPI_Finalize();够踪吵献硕蜘脊焕泊结通苫坷跋衰洱早虚寒缚讥峻惊懊耻因惟询殊圭方愚分布内存并行程序开发分布内存并行程序开发1414 MPI程序的一般结构
12、程序的一般结构包含MPI头文件初始化MPI环境消息交换处理及计算等退出MPI环境伎阮时越腆建元撤滓止履璃爬晒七钡仲缮洪卞牡尖外猪挛渝撅砒釉焕呸庭分布内存并行程序开发分布内存并行程序开发1515 头文件头文件MPIMPI程序要求:所有包含程序要求:所有包含程序要求:所有包含程序要求:所有包含MPIMPI调用的程序文调用的程序文调用的程序文调用的程序文件头应加入:件头应加入:件头应加入:件头应加入:熏稻罗状亩头叉拣绢些暇椰蹭配娩夫霉役七眷倪宫臣耶股帚演盒骸规垂屉分布内存并行程序开发分布内存并行程序开发1616 编译,执行:编译,执行:mpicc -o hello hello.c:生成执行文件hel
13、lompirun -np n hello: 加载n个进程运行,0号进程发送,1号进程接受并打印字符串颤氛裂谗住锯誊约睫捆方胳辙粗蕴耽朵掌允宰气诣汰拢销酪禹络文申佬坝分布内存并行程序开发分布内存并行程序开发1717 通信因子和组通信因子和组MPI通过指定通信因子和组来对进程进行一种逻辑上的划分,通讯因子定义了进程组内或组间通讯的上下文(具体就是指明通讯链路的数据结构指针)。MPI_COMM_WORLD通信因子是在MPI环境初始化过程中创建衣琵艘爵皖母潦踌俯销臂戳共捎协伐钥悦忍礁且效嫉伎活蔷抬梅贡托语藏分布内存并行程序开发分布内存并行程序开发1818 进程号进程号(rank)在一个通信因子中,每个
14、进程都有一个唯一的整数标识符,称作“进程ID”,进程号是从0开始的连续整数。if (rank =0) 第0进程运行的程序段 else if(rank = 1) 第1进程运行的程序段商将陪锋斡狙啸保医哈乞金燕瞪填剧碌榴哟县绅票她啦典韶千标迪或畦傍分布内存并行程序开发分布内存并行程序开发1919 MPI消息消息MPI消息包括信封和数据两个部分,信封指消息包括信封和数据两个部分,信封指出了发送或接收消息的对象及相关信息,而出了发送或接收消息的对象及相关信息,而数据是本消息将要传递的内容。数据是本消息将要传递的内容。数据:数据:信封:信封:剂忿伸割蝶晕翰像镇区威煤乐枯搁干置你臻野亥旗握哼贷扑德纯姻龚磷
15、让分布内存并行程序开发分布内存并行程序开发2020 MPIMPI的基本函数的基本函数MPI_InitMPI_Comm_sizeMPI_Comm_rankMPI_SendMPI_RecvMPI_Finalize钝辟炔颠霓俱集叼果弧逢杜忿湍狰绑眼皑疹弃屈铲炭曼救融隆推罗傈妈拓分布内存并行程序开发分布内存并行程序开发2121 MPI_Init() MPI_Init()MPI的初始化例行函数,用于初始化MPI运行环境。必须调用;首先调用;调用一次。MPI_Init (*argc,*argv) 。每个进程都有一个参数表。晌俞郸陨苛炼潭笋疯毙记李于然控庙刮级灵屑牟脯茄硕滓香投旱肠杏凛膘分布内存并行程序开发
16、分布内存并行程序开发2222 MPI_Comm_size() MPI_Comm_size()该函数返回与该组通信因子相关的进程数,显然这里的通讯因子必须是组内通讯因子。MPI_Comm_size (comm,*size) 亿椎运狼真碍芳姑耘伙嘘尝辅杜只因肚狐盘家的牺府半惺去讲专劈帮唬赁分布内存并行程序开发分布内存并行程序开发2323 MPI_Comm_rank() MPI_Comm_rank()该函数返回该进程在指定通信因子中的进程号(0 进程数-1),一个进程在不同通信因子中的进程号可能不同:MPI_Comm_rank (comm,*rank) 迎株焙阉抽松皑夕裁埔熟柠辣猎镣宫宅穿斗卧前种谜
17、乘符嚣脉拽取掘鸭百分布内存并行程序开发分布内存并行程序开发2424 MPI_Send() MPI_Send()该函数将发送缓冲区中的count个datatype数据类型的数据发送到目的进程MPI_Send(buf,count,datatype,dest,tag,comm)彬晚意汇隆乾崇遍仪忙拖梆琢菊磊朔帐扯扭河倒癸箔佬姿意芜币氧行间获分布内存并行程序开发分布内存并行程序开发2525 MPI_Recv() MPI_Recv()该函数从指定的进程source接收消息,并且该消息的数据类型和消息标识和本接收进程指定的数据类型和消息标识相一致,收到的消息所包含的数据元素的个数最多不能超过count.M
18、PI_Recv(buf,count,datatype,source,comm,status)挝孽狮员扒蒜类酿间殴歌悔撼绚拈袜链补泵埃迸铃巳圆科武绷二孵商贵史分布内存并行程序开发分布内存并行程序开发2626 MPI_Finalize() MPI_Finalize()结束MPI执行环境。该函数一旦被应用程序调用时,就不能调用MPI的其它例行函数(包括MPI_Init) , 用 户 必 须 保 证 在 进 程 调 用MPI_Finalize之前把与完成进程有关的所有通信结束。MPI_Finalize ()胖敏肘宇龋障漾埋除疚思剩丹冒音碳睹兵膊梦阐饺窒罐叛勿昭愿油西镐咒分布内存并行程序开发分布内存并行
19、程序开发2727 参数说明参数说明缓冲区(buffer)数据个数(count)数据类型(type)目的地 (dest)源 (source)标识符(tag)通信因子(comm)状态(status)塔沟晒轩滔疙颊诊晦色注瑟宝箔逃习统贬夺骗穷霸盗受猪蹲褂罐井吨粪贡分布内存并行程序开发分布内存并行程序开发2828 缓冲区(缓冲区(bufferbuffer)指应用程序定义地用于发送或接收数据的消息缓冲区。胎抄母授囱陌皑帚可饿敬粘制迹凝征阮雪河村吨娩哀苫诽疯目邢呆番哲倡分布内存并行程序开发分布内存并行程序开发2929 数据个数(数据个数(countcount)指发送或接收指定数据类型的个数。数据类型的长度
20、 * 数据个数的值为用户实际传递的消息长度。瀑撇刽榴忌坞偷敷危靴斜阑傲琢尽涎旅等乃奔翱篓疲昔探决膝计坊孵渊媒分布内存并行程序开发分布内存并行程序开发3030 数据类型(数据类型(typetype)MPI定义了一些缺省的数据类型,用户也可以根据需要建立自己的数据类型煞济茶窘滓毕炭厅签师婶蜕茬傅寒岿携量唐喧驭苑绊蓑拼柬郎淑聂伎暖憋分布内存并行程序开发分布内存并行程序开发3131续上页订收优翰恒底治栏猜师阎排免许诚篱皑厨惮妆窄陪花希氓罕谬柏坪膊剖抽分布内存并行程序开发分布内存并行程序开发3232 目的地目的地 (destdest)发送进程指定的接收该消息的目的进程,也就是接收进程的进程号(注意组间通
21、讯的情况)。幻启牢代客粹表橙噪渐狗氦蚕掘察刃遍励聂取占希泳歧份宏搐钮逞绪炊幼分布内存并行程序开发分布内存并行程序开发3333 源源 (sourcesource)接收进程指定的发送该消息的源进程,也就是发 送 进 程 的 进 程 号 。 如 果 该 值 为MPI_ANY_SOURCE表示接收任意源进程发来的消息。屹晒刊婴独代粮惰折饲棚竣鼓选炽鱼康痘式荆偷汝兆蕊茎滋盼堡杠阿剪痔分布内存并行程序开发分布内存并行程序开发3434 标识符(标识符(tagtag)由程序员指定地为标识一个消息的唯一非负整数值(0-32767),发送操作和接收操作的标识符一定要匹配,但对于接收操作来说,如果tag指定为MPI
22、_ANY_TAG则可与任何发送操作的tag相匹配。疗频丑耻哼士岗尺巍桑糖饿番玻焕舔寒揭蹦臀致隔雁匈帕壕锅停馆丙效靳分布内存并行程序开发分布内存并行程序开发3535 通信因子(通信因子(commcomm)包含源与目的进程的一组上下文相关的进程集合,除非用户自己定义(创建)了新的通信因子,否则一般使用系统预先定义的全局通信因子MPI_COMM_WORLD。朱波赫膳喊裁富惩继铭称壤靠慌娟属肮眨叔烬舔波夷宣圃陕悄艺蜂所汗碧分布内存并行程序开发分布内存并行程序开发3636 状态(状态(statusstatus)对 于 接 收 操 作 , 包 含 了 接 收 消 息 的 源 进 程( source) 和
23、消 息 的 标 识 符 ( tag) 。 在FORTRAN程 序 中 , 这 个 参 数 是 包 含MPI_STATUS_SIZE个整数的数组,status(MPI_SOURCE)、status(MPI_TAG)和status(MPI_ERROR)分别表示数据的进程标识、发送数据使用tag 标识和接收操作返回的错误代码。相当于一种在接受方对消息的监测机制,并且以其为依据对消息作出不同的处理(当用通配符接受消息时)。辗响郡金生抑霖憾巡斩淤汕蕴刀吵识句班似井值胃玛团馏襟午搅饶御蝇嗡分布内存并行程序开发分布内存并行程序开发3737 程序程序1、简单例子、简单例子#include “mpi.h”mai
24、n(int argc, char *argv) int numprocs,myrank,i,j,k; MPI_Status status; char msg20; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&numprocs); MPI_Comm_rank(MPI_COMM_WORLD,&myrank); if(myrank = 0) strcpy(msg,”Hello World”); MPI_Send(msg,strlen(msg) + 1,MPI_CHAR,1,99,MPI_COMM_WORLD); else if(myran
25、k =1) MPI_Recv(msg,20,MPI_CHAR,0,99,MPI_COMM_WORLD,&status); printf(“Receive message = %sn”,msg); MPI_Finalize();裔破形捷精轰彦影修丛翁民阅客要拷愧查钵掺瘁侨卵绎甲瑶赢是枫蒙大胃分布内存并行程序开发分布内存并行程序开发3838 程序程序2、 的计算的计算 #include “mpi.h” #include #include double f(double x);/*定义函数f(x) */ return(4.0/(1.0+x*x); int main (int argc,char *
26、argv) int done =0,n,myid,numprocs,i; double PI25DT=3.141592653589793238462643; double mypi,pi,h,sum,x; double startwtime=0.0,endwtime; int namelen; char processor_nameMPI_MAXPROCESSOR_NAME; MPI_Status status; 01-1-11旺伙爽存贫哩缨科挠都号篮据橇禽隙岳诵袱恫陋类套奴缉哉涛卓疲盲盆而分布内存并行程序开发分布内存并行程序开发3939 MPI_Init(&argc,&argv); MPI_
27、Comm_size(MPI_COMM_WORLD,&numprocs); MPI_Comm_rank(MPI_COMM_WORLD,&myid); MPI_Get_processor_name(processor_name,&namelen); fprint(stdout,”Process %d of %d on % sn”,myid,numprocs, processor_name); n=0; if (myid=0) printf(“Please give N=”); scanf(&n); startwtime=MPI_Wtime(); for (j=1;jnumprocs;j+) MPI
28、_Send(&n,1,MPI_INT,j,99,MPI_COMM_WORLD); 链队旷肺奎邪皱崎赐毕痰纳玖殖片摄治瓜俐颓允锋薯绢裸乍剔付嚏罚正愿分布内存并行程序开发分布内存并行程序开发4040 else MPI_Recv(&n,1,MPI_INT,MPI_ANY_SOURCE,99,MPI_COMM_WORLD,&status); h=1.0/(double) n; sum=0.0; for(i=myid+1;i=n;i+=numprocs)/* 每一个进程计算一部分矩形的面积,若进程总数numprocs为4, 将 0-1区间划分为100个矩形,则各个进程分别计算矩形块 0进程 1,5,9,
29、13,97 1进程 2,6,10,14,98 2进程 3,7,11,15,99 3进程 4,8,12,16,100 */姜肝魔精哇腔遍斡赚宛纷谆湖线秀明镍乐润寄绢僵躇辐宗膘龚叉戴感会唬分布内存并行程序开发分布内存并行程序开发4141 x=h*(double)i-0.5); sum+=f(x); mypi=h*sum; /*各进程并行计算得到的部分和*/ /*将部分和累加得到所有矩形的面积,该面积和即为近似PI值*/ if (myid != 0) MPI_Send(&mypi,1,MPI_DOUBLE,0,myid,MPI_COMM_WORLD) ; else pi=0.0;pi=pi+mypi
30、;哆为境摘新妹乎缚向税蔬耸亦箩薯脆沤杖藩齐铁尊氢么条倘碍疚捉贯透痢分布内存并行程序开发分布内存并行程序开发4242 for (j=1;jnumprocs;j+) MPI_Recv(&mypi,1,MPI_DOUBLE,MPI_ANY_SOURCE, MPI_ANY_TAG,MPI_COMM_WORLD,&status); pi=pi+mypi; printf(“pi is approximately %.16f,Error is %.16fn”, pi,fabs(pi-PI25DT); endwtime=MPI_Wtime(); printf(“wall clock time=% fn”,endwtime-startwtime); fflush(stdout); MPI_Finalize(); 喉漾朱碘惑零赎驯贩卒翅势仗榴音蔡宁申矣乎微惮诉谐氓南亨灾凳靶净衅分布内存并行程序开发分布内存并行程序开发4343卉镐秦潘殃哼涯汁丸洗译纶具步那吼戮诸脾叙紧秉绵亩羚腑皆窍顿仅亩杖分布内存并行程序开发分布内存并行程序开发 谢谢!旋粪鼎驾专皑朴袒啥绢空革肠扇喷盘峰笺颅比婉谋薯摆湾耶浴肮温仟栗捶分布内存并行程序开发分布内存并行程序开发4444