并行计算.

Slides:



Advertisements
Similar presentations
MPI 简介 MPI 及其历史: 消息传递接口( Message Passing Interface ,简称 MPI )是 一种编程接口标准,而不是一种具体的编程语言。 由消息传递接口论坛( Message Passing Interface Forum , 简称 MPIF )发起讨论并进行规范化的。
Advertisements

While 迴圈 - 不知重複執行次數
美味料理 5223汪芮臣.
郎显宇 中国科学院计算机网络信息中心 超级计算中心
2011年10月31日是一个令人警醒的日子,世界在10月31日迎来第70亿人口。当日凌晨,成为象征性的全球第70亿名成员之一的婴儿在菲律宾降生。 ?
合 同 法 主讲人: 教材:《合同法学》(崔建远) 2017/3/10.
初级会计实务 第八章 产品成本核算 主讲人:杨菠.
中考阅读 复习备考交流 西安铁一中分校 向连吾.
周纯葆 中国科学院计算机网络信息中心 超级计算中心
中央广播电视大学开放教育 成本会计(补修)期末复习
人教版义务教育课程标准实验教科书 小学数学四年级上册第七单元《数学广角》 合理安排时间 248.
中考语文积累 永宁县教研室 步正军 2015.9.
第二章 JAVA语言基础.
机群应用开发 并行编程原理及 程序设计 Parallel Programming: Fundamentals and Implementation 曙光信息产业有限公司 2017年9月 2017年9月 MPI并行程序设计.
小学数学知识讲座 应用题.
倒装句之其他句式.
Tree(樹) 什麼是「樹」? 「樹」的範例 「樹」的定義 「樹」的表示法.
第 22 课 孙中山的民主追求 1 .近代变法救国主张的失败教训: “师夷之长技以制 夷”“中体西用”、兴办洋务、变法维新等的失败,使孙中山
Operating System Concepts 作業系統原理 Chapter 3 行程觀念 (Process Concept)
MPI并行程序设计简介 曙光信息产业(北京)有限公司 2018年11月.
并行算法实践.
消息传递并行编程环境 王彦棡 2010年5月.
佇列 (Queue).
周纯葆 中国科学院计算机网络信息中心 超级计算中心
并行编程原理及 程序设计 Parallel Programming: Fundamentals and Implementation
C++程序设计 第二讲 清华大学软件学院.
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
机群应用开发 并行编程原理及 程序设计 Parallel Programming: Fundamentals and Implementation 曙光信息产业股份有限公司 解决方案中心 高性能计算方案部 年11月.
MPI并行编程      报告人:李俊照.
第四讲 MPI并行程序设计 课程网站:CourseGrading buaa.edu.cn 主讲教师: 赵长海
第十一章 文件 文件概述 文件操作 文件操作实例 本章小结 作业: 练习:
并行算法实践 上篇 并行程序设计导论.
基于MPI的并行程序设计 王振海 西北工业大学理学院 西北工业大学高性能计算研究与发展中心 2018/11/28.
Chapter 3 行程觀念 (Process Concept)
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Function.
程序设计期末复习 黎金宁
第三章 C++中的C 面向对象程序设计(C++).
计算机网络讲义 第5章 批量数据处理—数组 一维数组 排序和查找 二维数组 字符串.
进程操作.
第3章 堆栈和队列 堆栈 堆栈应用 队列 队列应用 优先级队列 主要知识点.
第3讲 C++程序控制结构 3.1 顺序结构 3.2 分支结构 3.3 循环结构 3.4 转向控制 3.5 综合案例分析.
電腦解題─流程圖簡介 臺北市立大同高中 蔡志敏老師.
6.3 遍历二叉树和线索二叉树(知识点二) 遍历二叉树 一、问题的提出
并行计算简介 高性能事业部:曹振南 年4月.
十二、并行程序设计基础.
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
第二章Java基本程序设计.
C语言概述 第一章.
程式結構&語法.
作業系統 第四章 行程.
Oop8 function函式.
Chap 5 函数 5.1 计算圆柱体积 5.2 使用函数编写程序 5.3 变量与函数.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
第二章 Java语法基础.
MPI 第三章 需要邊界資料交換的平行程式.
第二章 类型、对象、运算符和表达式.
第二章 基本数据类型 ——数据的表示.
授课老师:龚涛 信息科学与技术学院 2016年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
挑戰C++程式語言 ──第9章 函數.
第八节 算术运算符和算术表达式.
第五章 逻辑运算和判断选取控制 §5.1 关系运算符和关系表达式
第十二章 位运算.
本章主題 C++的程式結構 資料型態與宣告 算術運算 簡易的輸入輸出指令 程式編譯(Compile)的過程與原理.
PPT注意事项: 当前PPT课件文件必须和提供的源代码文件夹“代码”在同一目录中即不要移动文件夹“代码”的默认位置。
多重條件選擇敘述
畢氏定理(百牛大祭)的故事 張美玲 製作 資料來源:探索數學的故事(凡異出版社).
本节内容 指针类型 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
102年人事預算編列說明 邁向頂尖大學辦公室製作.
Presentation transcript:

并行计算

上机安排 学时:40/20 上机时间:周六18:30 - 21:30 第十周到第十四周,5月5日第一次上机 上机地点:电三楼406室

上机题目 利用OpenMP、MPI进行简单程序编写测试;测试并行计算系统性能 MPI编程 (1) - 蒙特卡罗模拟计算 MPI 编程 (2)- 简化N体问题计算 并行排序算法的实现和性能比较 并行程序应用优化实例的设计与实现(选做)

十五、分布存储系统并行编程

分布存储系统并行编程 14.1 基于消息传递的并行编程 14.2 MPI并行编程 6个基本函数组成的MPI子集 MPI消息 点对点通信 群集通信

SPMD和MPMD SPMD MPMD 各个进程是同构的,多个进程对不同的数据执行相同的代码(一般是数据并行) 常对应并行循环,数据并行结构,单代码 MPMD 各个进程是异构的, 多个进程执行不同的代码(一般是任务并行,或功能并行) 常对应并行块,多代码 要为有1000个处理器的计算机编写一个完全异构的并行程序是很困难的

SPMD和MPMD SPMD程序的构造方法 用单代码方法说明SPMD parfor (i=0; i<=N, i++) foo(i) 用户需写一个以下程序: pid=my_process_id(); numproc=number_of _processes(); parfor (i=pid; i<=N, i=i+numproc) foo(i) 此程序经编译后生成可执行程序A, 用shell脚本将它加载到N个处理结点上: run A –numnodes N 用数据并行程序的构造方法 要说明以下SPMD程序: parfor (i=0; i<=N, i++) { C[i]=A[i]+B[i]; } 用户可用一条数据赋值语句: C=A+B 或 forall (i=1,N) C[i]=A[i]+B[i]

SPMD和MPMD MPMD程序的构造方法 用多代码方法说明MPMD 对不提供并行块或并行循环的语言 要说明以下MPMD程序: parbegin S1 S2 S3 parend 用户需写3个程序, 分别编译生成3个可执行程序S1 S2 S3, 用shell脚本将它们加载到3个处理结点上: run S1 on node1 run S2 on node1 run S3 on node1 S1, S2和S3是顺序语言程序加上进行交互的库调用. 用SPMD伪造MPMD 要说明以下MPMD程序: parbegin S1 S2 S3 parend 可以用以下SPMD程序: parfor (i=0; i<3, i++) { if (i=0) S1 if (i=1) S2 if (i=2) S3 } 因此, 对于可扩展并行机来说, 只要支持SPMD就足够了

分布存储系统并行编程 14.1 基于消息传递的并行编程 14.2 MPI并行编程 6个基本函数组成的MPI子集 MPI消息 点对点通信 群集通信

MPI简介 MPI(Message Passing Interface )是一个消息传递接口标准 MPI提供与C/C++和Fortran语言的绑定

MPI简介 MPI的版本 MPICH:http://www-unix.mcs.anl.gov/mpi/mpich LAM (Local Area Multicomputer): http://www.lam-mpi.org Open-MPI: http://www.open-mpi.org/ CHIMP: ftp://ftp.epcc.ed.ac.uk/pub/chimp/release/

6个基本函数组成的MPI子集 #include "mpi.h" /*MPI头函数,提供了MPI函数和数据类型定义*/ int main( int argc, char** argv ) { int rank, size, tag=1; int senddata,recvdata; MPI_Status status; MPI_Init(&argc, &argv); /*MPI的初始化函数*/ MPI_Comm_rank(MPI_COMM_WORLD, &rank); /*该进程编号*/ MPI_Comm_size(MPI_COMM_WORLD, &size); /*总进程数目*/

6个基本函数组成的MPI子集 if (rank==0){ senddata=9999; MPI_Send( &senddata, 1, MPI_INT, 1, tag, MPI_COMM_WORLD); /*发送数据到进程1*/ } if (rank==1) MPI_Recv(&recvdata, 1, MPI_INT, 0, tag, MPI_COMM_WORLD, &status); /*从进程0接收数据*/ MPI_Finalize(); /*MPI的结束函数*/ return (0);

6个基本函数组成的MPI子集 MPI初始化:通过MPI_Init函数进入MPI环境并完成所有的初始化工作。 int MPI_Init( int *argc, char * * * argv ) MPI结束:通过MPI_Finalize函数从MPI环境中退出。 int MPI_Finalize(void)

6个基本函数组成的MPI子集 获取进程的编号:调用MPI_Comm_rank函数获得当前进程在指定通信域中的编号,将自身与其他程序区分。 int MPI_Comm_rank(MPI_Comm comm, int *rank) 获取指定通信域的进程数:调用MPI_Comm_size函数获取指定通信域的进程个数,确定自身完成任务比例。 int MPI_Comm_size(MPI_Comm comm, int *size)

6个基本函数组成的MPI子集 消息发送:MPI_Send函数用于发送一个消息到目标进程。 int MPI_Send(void *buf, int count, MPI_Datatype dataytpe, int dest, int tag, MPI_Comm comm) 消息接受:MPI_Recv函数用于从指定进程接收一个消息 int MPI_Recv(void *buf, int count, MPI_Datatype datatyepe,int source, int tag, MPI_Comm comm, MPI_Status *status)

MPI消息 一个消息好比一封信 消息的内容即信的内容,在MPI中称为消息缓冲(Message Buffer) 消息的接收/发送者即信的地址,在MPI中称为消息信封(Message Envelop)

MPI消息 MPI中,消息缓冲由三元组<起始地址,数据个数,数据类型>标识 消息信封由三元组<源/目标进程,消息标签,通信域>标识 三元组的方式使得MPI可以表达更为丰富的信息,功能更强大

MPI消息(数据类型) MPI的消息类型分为两种:预定义类型和派生数据类型(Derived Data Type) 预定义数据类型:MPI支持异构计算(Heterogeneous Computing),它指在不同计算机系统上运行程序,每台计算可能有不同生产厂商,不同操作系统。 MPI通过提供预定义数据类型来解决异构计算中的互操作性问题,建立它与具体语言的对应关系。 派生数据类型:MPI引入派生数据类型来定义由数据类型不同且地址空间不连续的数据项组成的消息。

MPI消息(数据类型)

MPI消息(数据类型) MPI提供了两个附加类型:MPI_BYTE和MPI_PACKED 。

MPI消息(数据类型) double A[100]; MPI_Pack_size (50,MPI_DOUBLE,comm,&BufferSize); TempBuffer = malloc(BufferSize); j = sizeof(MPI_DOUBLE); Position = 0; for (i=0;i<50;i++) MPI_Pack(A+i*j,1,MPI_DOUBLE,TempBuffer,BufferSize,&Position,comm); MPI_Send(TempBuffer,Position,MPI_PACKED,destination,tag,comm); MPI_Pack_size函数来决定用于存放50个MPI_DOUBLE数据项的临时缓冲区的大小 调用malloc函数为这个临时缓冲区分配内存 for循环中将数组A的50个偶序数元素打包成一个消息并存放在临时缓冲区

MPI消息(数据类型) 消息打包,然后发送 MPI_Pack(buf, count, dtype, //以上为待打包消息描述 packbuf, packsize, packpos, //以上为打包缓冲区描述 communicator) 消息接收,然后拆包 MPI_Unpack(packbuf, packsize, packpos, //以上为拆包缓冲区描述 buf, count, dtype, // 以上为拆包消息描述 communicatior)

MPI消息(数据类型) 派生数据类型可以用类型图来描述,这是一种通用的类型描述方法,它是一系列二元组<基类型,偏移>的集合,可以表示成如下格式: {<基类型0,偏移0>,···,<基类型n-1,偏移n-1>} 在派生数据类型中,基类型可以是任何MPI预定义数据类型,也可以是其它的派生数据类型,即支持数据类型的嵌套定义。 阴影部分是基类型所占用的空间,其它空间可以是特意留下的,也可以是为了方便数据对齐。

MPI消息(数据类型) MPI提供了全面而强大的构造函数(Constructor Function)来定义派生数据类型。 函数名 含义 MPI_Type_contiguous 定义由相同数据类型的元素组成的类型 MPI_Type_vector 定义由成块的元素组成的类型,块之间具有相同间隔 MPI_Type_indexed 定义由成块的元素组成的类型,块长度和偏移由参数指定 MPI_Type_struct 定义由不同数据类型的元素组成的类型 MPI_Type_commit 提交一个派生数据类型 MPI_Type_free 释放一个派生数据类型

MPI消息(数据类型) double A[100]; MPI_Datatype EvenElements; ··· MPI_Type_vector(50, 1, 2, MPI_DOUBLE, &EvenElements); MPI_Type_commit(&EvenElements); MPI_Send(A, 1, EvenElements, destination, ···); 首先声明一个类型为MPI_Data_type的变量EvenElements 调用构造函数MPI_Type_vector(count, blocklength, stride, oldtype, &newtype)来定义派生数据类型 新的派生数据类型必须先调用函数MPI_Type_commit获得MPI系统的确认后才能调用MPI_Send进行消息发送

MPI消息(数据类型) 调用构造函数MPI_Type_vector(count, blocklength, stride, oldtype, &newtype)来定义派生数据类型。 该newtype由count个数据块组成。 而每个数据块由blocklength个oldtype类型的连续数据项组成。 参数stride定义了两个连续数据块的起始位置之间的oldtype类型元素的个数。因此,两个块之间的间隔可以由(stride-blocklength)来表示。 MPI_Type_vector(50,1,2,MPI_DOUBLE,&EvenElements)函数调用产生了派生数据类型EvenElements,它由50个块组成,每个块包含一个双精度数,后跟一个(2-1)MPI_DOUBLE(8字节)的间隔,接在后面的是下一块。上面的发送语句获取数组A的所有序号为偶数的元素并加以传递。

MPI消息(数据类型) MPI_Type_vector(count, blocklength, stride, oldtype, &newtype) stride oldtype …… oldtype …… oldtype …… oldtype …… blocklength blocklength count

MPI消息(数据类型) 1 2 3 4 5 6 7 8 9 左图10×10整数矩阵的所有偶序号的行: MPI_Type_vector( 1 2 3 4 5 6 7 8 9 左图10×10整数矩阵的所有偶序号的行: MPI_Type_vector( 5, // count 10, // blocklength 20, // stride MPI_INT, //oldtype &newtype )

MPI消息(消息标签) 为什么需要消息标签? 当发送者连续发送两个相同类型消息给同一个接收者,如果没有消息标签,接收者将无法区分这两个消息 这段代码打算传送A的前32个字节进入X,传送B的前16个字节进入Y。但是,尽管消息B后发送,但可能先到达进程Q,就会被第一个接收函数接收在X中。使用标签可以避免这个错误 Process P: Send(A, 32, Q) Send(B, 16, Q) Process Q: recv (X, 32, P) recv (Y, 16, P) Process P: send(A, 32, Q, tag1) send(B, 16, Q, tag2) Process Q: recv (X, 32, P, tag1) recv (Y, 16, P, tag2)

MPI消息(消息标签) 添加标签使得服务进程可以对两个不同的用户进程分别处理,提高灵活性

MPI消息(通信域) 通信域(Communicator)包括进程组(Process Group)和通信上下文(Communication Context)等内容,用于描述通信进程间的通信关系。 通信域分为组内通信域和组间通信域,分别用来实现MPI的组内通信(Intra-communication)和组间通信(Inter-communication)。

MPI消息(通信域) 进程组是进程的有限、有序集。 有限意味着,在一个进程组中,进程的个数n是有限的,这里的n称为进程组大小(Group Size)。 有序意味着,进程的编号是按0,1,…,n-1排列的 一个进程用它在一个通信域(组)中的编号进行标识。组的大小和进程编号可以通过调用以下的MPI函数获得: MPI_Comm_size(communicator, &group_size) MPI_Comm_rank(communicator, &my_rank)

MPI消息(通信域) 通信上下文:安全的区别不同的通信以免相互干扰 进程组和通信上下文结合形成了通信域 通信上下文不是显式的对象,只是作为通信域的一部分出现 进程组和通信上下文结合形成了通信域 MPI_COMM_WORLD是所有进程的集合

MPI消息(通信域) MPI提供丰富的函数用于管理通信域 函数名 含义 MPI_Comm_size 获取指定通信域中进程的个数 MPI_Comm_rank 获取当前进程在指定通信域中的编号 MPI_Comm_compare 对给定的两个通信域进行比较 MPI_Comm_dup 复制一个已有的通信域生成一个新的通信域,两者除通信上下文不同外,其它都一样。 MPI_Comm_create 根据给定的进程组创建一个新的通信域 MPI_Comm_split 从一个指定通信域分裂出多个子通信域,每个子通信域中的进程都是原通信域中的进程。 MPI_Comm_free 释放一个通信域

MPI消息(通信域) 一个在MPI中创建新通信域的例子 MPI_Comm MyWorld, SplitWorld; int my_rank,group_size, Color, Key; MPI_Init(&argc, &argv); MPI_Comm_dup(MPI_COMM_WORLD,&MyWorld); MPI_Comm_rank(MyWorld,&my_rank); MPI_Comm_size(MyWorld,&group_size); Color=my_rank%3; Key=my_rank/3; MPI_Comm_split(MyWorld,Color,Key,&SplitWorld);

MPI消息(通信域) MPI_Comm_dup(MPI_COMM_WORLD,&MyWorld)创建了一个新的通信域MyWorld,它包含了与原通信域MPI_COMM_WORLD相同的进程组,但具有不同的通信上下文。 MPI_Comm_split(MyWorld,Color,Key,&SplitWorld)函数调用则在通信域MyWorld的基础上产生了几个分割的子通信域。原通信域MyWorld中的进程按照不同的Color值处在不同的分割通信域中,每个进程在不同分割通信域中的进程编号则由Key值来标识。 Rank in MyWorld 1 2 3 4 5 6 7 8 9 Color Key Rank in SplitWorld(Color=0) Rank in SplitWorld(Color=1) Rank in SplitWorld(Color=2)

MPI消息(通信域) 组间通信域是一种特殊的通信域,该通信域包括了两个进程组,分属于两个进程组的进程之间通过组间通信域实现通信。 一般把调用进程所在的进程组称为本地进程组,而把另外一个称为远程进程组。 函数名 含义 MPI_Comm_test_inter 判断给定的通信域是否为组间通信域 MPI_Comm_remote_size 获取指定组间通信域中远程进程组的大小 MPI_Comm_remote_group 返回给定组间通信域的远程进程组 MPI_Intercomm_creat 根据给定的两个组内通信域生成一个组间通信域。 MPI_Intercomm_merge 将给定组间通信域包含的两个进程组合并,形成一个新的组内通信域

MPI消息(消息状态) 消息状态(MPI_Status类型)存放接收消息的状态信息,包括: 是消息接收函数MPI_Recv的最后一个参数。 消息的源进程标识--MPI_SOURCE 消息标签--MPI_TAG 错误状态--MPI_ERROR 其他--包括数据项个数等,但多为系统保留的。 是消息接收函数MPI_Recv的最后一个参数。 当一个接收者从不同进程接收不同大小和不同标签的消息时,消息的状态信息非常有用。

MPI消息(消息状态) 假设多个客户进程发送消息给服务进程请求服务,通过消息标签来标识客户进程,从而服务进程采取不同的服务 while (true){ MPI_Recv(received_request,100,MPI_BYTE,MPI_Any_source,MPI_Any_tag,comm,&Status); switch (Status.MPI_Tag) { case tag_0: perform service type0; case tag_1: perform service type1; case tag_2: perform service type2; }

点对点通信 MPI的点对点通信(‘Point-to-Point Communication )同时提供了阻塞和非阻塞两种通信机制 。 同时也支持多种通信模式。 不同通信模式和不同通信机制的结合,便产生了非常丰富的点对点通信函数。

点对点通信(通信模式) 通信模式(Communication Mode)指的是缓冲管理,以及发送方和接收方之间的同步方式。 共有下面四种通信模式 同步(synchronous)通信模式 缓冲(buffered)通信模式 标准(standard)通信模式 就绪(ready)通信模式

点对点通信(通信模式) 同步通信模式:只有相应的接收过程已经启动,发送过程才正确返回。 因此,同步发送返回后,表示发送缓冲区中的数据已经全部被系统缓冲区缓存,并且已经开始发送。 当同步发送返回后,发送缓冲区可以被释放或者重新使用。 S R Synchronous 1 2 3

点对点通信(通信模式) 缓冲通信模式:缓冲通信模式的发送不管接收操作是否已经启动都可以执行。 但是需要用户程序事先申请一块足够大的缓冲区,通过MPI_Buffer_attch实现,通过MPI_Buffer_detach来回收申请的缓冲区。 S R Buffer 1 2

点对点通信(通信模式) 标准通信模式:是否对发送的数据进行缓冲由MPI的实现来决定,而不是由用户程序来控制。 发送可以是同步的或缓冲的,取决于实现 Standard S R 1

点对点通信(通信模式) 就绪通信模式:发送操作只有在接收进程相应的接收操作已经开始才进行发送。 当发送操作启动而相应的接收还没有启动,发送操作将出错。就绪通信模式的特殊之处就是接收操作必须先于发送操作启动。 S R Ready 1 2

点对点通信(通信模式) 阻塞和非阻塞通信的主要区别在于返回后的资源可用性 阻塞通信返回的条件: 通信操作已经完成,即消息已经发送或接收 调用的缓冲区可用。若是发送操作,则该缓冲区可以被其它的操作更新;若是接收操作,该缓冲区的数据已经完整,可以被正确引用。

点对点通信(通信模式) MPI的发送操作支持四种通信模式,它们与阻塞属性一起产生了MPI中的8种发送操作。 非阻塞通信返回后并不意味着通信操作的完成,MPI还提供了对非阻塞通信完成的检测,主要的有两种:MPI_Wait函数和MPI_Test函数。

点对点通信(通信模式) MPI的点对点通信操作 MPI 原语 阻塞 非阻塞 Standard Send MPI_Send MPI_Isend Synchronous Send MPI_ Ssend MPI_ Issend Buffered Send MPI_ Bsend MPI_ Ibsend Ready Send MPI_ Rsend MPI_ Irsend Receive MPI_Recv MPI_Irecv Completion Check MPI_Wait MPI_Test

点对点通信(通信模式) 在阻塞通信的情况下,通信还没有结束的时候,处理器只能等待,浪费了计算资源。 一种常见的技术就是设法使计算与通信重叠,非阻塞通信可以用来实现这一目的。 一条三进程的流水线,一个进程连续地从左边的进程接收一个输入数据流,计算一个新的值,然后将它发送给右边的进程。 while (Not_Done){ MPI_Irevc(NextX, … ); MPI_Isend(PreviousY, … ); CurrentY=Q(CurrentX); }

点对点通信(通信模式) 非阻塞通信中,双缓冲是一种常用的方法。 代码如下 我们需要为X和Y各自准备两个单独的缓冲,当接收进程向缓冲中放下一个X时,计算进程可能从另一个缓冲中读当前的X。 我们需要确信缓冲中的数据在缓冲被更新之前使用 。 代码如下 while (Not_Done){ if (X==Xbuf0) {X=Xbuf1; Y=Ybuf1; Xin=Xbuf0; Yout=Ybuf0;} else {X=Xbuf0; Y=Ybuf0; Xin=Xbuf1; Yout=Ybuf1;} MPI_Irevc(Xin, …, recv_handle); MPI_Isend(Yout, …, send_handle); Y=Q(X); /* 重叠计算*/ MPI_Wait(recv_handle,recv_status); MPI_Wait(send_handle,send_status); }

点对点通信(通信模式) send_handle和revc_handle分别用于检查发送接收是否完成。 检查发送接收通过调用MPI_Wait(Handle, Status)来实现,它直到Handle指示的发送或接收操作已经完成才返回 。 另一个函数MPI_Test(Handle, Flag, Status)只测试由Handle指示的发送或接收操作是否完成,如果完成,就对Flag赋值True,这个函数不像MPI_Wait,它不会被阻塞。

点对点通信-Send-Recv 给一个进程发送消息,从另一个进程接收消息; 特别适用于在进程链(环)中进行“移位”操作,而避免在通讯为阻塞方式时出现死锁。 MPI_Sendrecv( sendbuf, sendcount, sendtype, dest, sendtag, //以上为消息发送的描述 recvbuf, recvcount, recvtype, source, recvtag, // 以上为消息接收的描述 comm, status)

群集通信 群集通信(Collective Communications)是一个进程组中的所有进程都参加的全局通信操作。 群集通信实现三个功能:通信、聚集和同步 通信功能主要完成组内数据的传输 聚集功能在通信的基础上对给定的数据完成一定的操作 同步功能实现组内所有进程在执行进度上取得一致

群集通信 群集通信,按照通信方向的不同,又可以分为三种:一对多通信,多对一通信和多对多通信。 一对多通信:一个进程向其它所有的进程发送消息,这个负责发送消息的进程叫做Root进程。 多对一通信:一个进程负责从其它所有的进程接收消息,这个接收的进程也叫做Root进程。 多对多通信:每一个进程都向其它所有的进程发送或者接收消息。

群集通信 类型 函数名 含义 通信 MPI_Bcast 一对多广播同样的消息 MPI_Gather 多对一收集各个进程的消息 MPI_Gatherv MPI_Gather的一般化 MPI_Allgather 全局收集 MPI_Allgatherv MPI_Allgather的一般化 MPI_Scatter 一对多散播不同的消息 MPI_Scatterv MPI_Scatter的一般化 MPI_Alltoall 多对多全局交换消息 MPI_Alltoallv MPI_Alltoall的一般化 聚集 MPI_Reduce 多对一归约 MPI_Allreduce MPI_Reduce的一般化 MPI_Reduce_scatter MPI_Scan 扫描 同步 MPI_Barrier 路障同步

群集通信 广播是一对多通信的典型例子,其调用格式如下: MPI_Bcast(Address, Count, Datatype, Root, Comm)

群集通信 广播的特点 标号为Root的进程发送相同的消息给通信域Comm中的所有进程。 消息的内容如同点对点通信一样由三元组<Address, Count, Datatype>标识。 对Root进程来说,这个三元组既定义了发送缓冲也定义了接收缓冲。对其它进程来说,这个三元组只定义了接收缓冲

群集通信 收集是多对一通信的典型例子,其调用格式下: MPI_Gather(SendAddress, SendCount, SendDatatype, RecvAddress, RecvCount, RecvDatatype, Root, Comm)

群集通信 收集的特点 在收集操作中,Root进程从进程域Comm的所有进程(包括它自已)接收消息。 这n个消息按照进程的标识rank排序进行拼接,然后存放在Root进程的接收缓冲中。 接收缓冲由三元组<RecvAddress, RecvCount, RecvDatatype>标识,发送缓冲由三元组<SendAddress, SendCount, SendDatatype>标识,所有非Root进程忽略接收缓冲。

群集通信 散播是一个一对多操作,其调用格式如下: MPI_Scatter(SendAddress, SendCount, SendDatatype, RecvAddress, RecvCount, RecvDatatype, Root, Comm)

群集通信 散播的特点 Scatter执行与Gather相反的操作。 Root进程给所有进程(包括它自已)发送一个不同的消息,这n (n为进程域comm包括的进程个数)个消息在Root进程的发送缓冲区中按进程标识的顺序有序地存放。 每个接收缓冲由三元组<RecvAddress, RecvCount, RecvDatatype>标识,所有的非Root进程忽略发送缓冲。对Root进程,发送缓冲由三元组<SendAddress, SendCount, SendDatatype>标识。

群集通信 全局收集多对多通信的典型例子,其调用格式如下: MPI_Allgather(SendAddress, SendCount, SendDatatype, RecvAddress, RecvCount, RecvDatatype, Comm) Allgather操作相当于每个进程都作为ROOT进程执行了一次Gather调用,即每一个进程都按照Gather的方式收集来自所有进程(包括自己)的数据。

群集通信 全局交换也是一个多对多操作,其调用格式如下: MPI_Alltoall(SendAddress, SendCount, SendDatatype, RecvAddress, RecvCount, RecvDatatype, Comm)

群集通信 全局交换的特点 在全局交换中,每个进程发送一个消息给所有进程(包括它自已)。 这n (n为进程域comm包括的进程个数)个消息在它的发送缓冲中以进程标识的顺序有序地存放。从另一个角度来看这个通信,每个进程都从所有进程接收一个消息,这n个消息以标号的顺序被连接起来,存放在接收缓冲中。 全局交换等价于每个进程作为Root进程执行了一次散播操作。

群集通信 同步功能用来协调各个进程之间的进度和步伐 。目前MPI的实现中支持一个同步操作,即路障同步(Barrier)。 路障同步的调用格式如下: MPI_Barrier(Comm) 在路障同步操作MPI_Barrier(Comm)中,通信域Comm中的所有进程相互同步。 在该操作调用返回后,可以保证组内所有的进程都已经执行完了调用之前的所有操作,可以开始该调用后的操作。

群集通信 群集通信的聚合功能使得MPI进行通信的同时完成一定的计算。 MPI聚合的功能分三步实现 首先是通信的功能,即消息根据要求发送到目标进程,目标进程也已经收到了各自需要的消息; 然后是对消息的处理,即执行计算功能; 最后把处理结果放入指定的接收缓冲区。 MPI提供了两种类型的聚合操作: 归约和扫描。

群集通信 归约的调用格式如下: MPI_Reduce(SendAddress, RecvAddress, Count, Datatype, Op, Root, Comm) 归约的特点 归约操作对每个进程的发送缓冲区(SendAddress)中的数据按给定的操作进行运算,并将最终结果存放在Root进程的接收缓冲区(RecvAddress)中。 参与计算操作的数据项的数据类型在Datatype域中定义,归约操作由Op域定义。 归约操作可以是MPI预定义的,也可以是用户自定义的。 归约操作允许每个进程贡献向量值,而不只是标量值,向量的长度由Count定义。

群集通信 MPI_Reduce: root=0,Op=MPI_SUM MPI_Allreduce: Op=MPI_SUM 归约前的发送缓冲区 B0 B1 B2 P2: C0 C1 C2

群集通信 MPI_Reduce: root=P0,Op=MPI_SUM 归约后的接收缓冲区 P0: A0+B0+C0 A1+B1+C1

群集通信 MPI_Allreduce: Op=MPI_SUM 归约后的接收缓冲区 P0: A0+B0+C0 A1+B1+C1

群集通信 扫描的调用格式如下: MPI_scan(SendAddress, RecvAddress, Count, Datatype, Op, Comm) 扫描的特点 可以把扫描操作看作是一种特殊的归约,即每一个进程都对排在它前面的进程进行归约操作。 MPI_SCAN调用的结果是,对于每一个进程i,它对进程0,1,…,i的发送缓冲区的数据进行了指定的归约操作。 扫描操作也允许每个进程贡献向量值,而不只是标量值。向量的长度由Count定义。

群集通信 MPI_scan:Op=MPI_SUM 扫描前发送缓冲区: P0: A0 A1 A2 P1: B0 B1 B2 P2: C0 C1

群集通信 MPI_scan:Op=MPI_SUM 扫描后接收缓冲区: P0: A0 A1 A2 P1: A0+B0 A1+B1 A2+B2 A0+B0+C0 A1+B1+C1 A2+B2+C2

群集通信 所有的MPI群集通信操作都具有如下的特点: 通信域中的所有进程必须调用群集通信函数。只有通信域中的一部分成员调用了群集通信函数而其它没有调用,是错误的。 除MPI_Barrier以外,每个群集通信函数使用类似于点对点通信中的标准、阻塞的通信模式。也就是说,一个进程一旦结束了它所参与的群集操作就从群集函数中返回,但是并不保证其它进程执行该群集函数已经完成。 一个群集通信操作是不是同步操作取决于实现。MPI要求用户负责保证他的代码无论实现是否同步都必须是正确的。 一般可认为有隐含的同步。 所有参与群集操作的进程中,Count和Datatype必须是兼容的。 群集通信中的消息没有消息标签参数,消息信封由通信域和源/目标定义。例如在MPI_Bcast中,消息的源是Root进程,而目标是所有进程(包括Root)。

作业 15.1 15.3 15.13 ①