入门并行编程MPI(一)

MPI(消息传递接口)是一个标准化和可移植的消息系统(函数库)。该标准定义了在 Fortran 77、C 和 C++ 中编写具有消息传递的可移植程序时使用的库函数的语法和语义。

换句话说,MPI 是一种用于在并行应用程序的分支之间提供通信的软件工具。

介绍

以前,每个并行计算机制造商都开发了自己的库。直到最后,MPI 标准被开发出来。开发人员利用了许多现有消息传递系统最吸引人的特性,而不是将其中一个系统作为标准进行调整。

MPI 的主要目标是实现所开发软件对不同并行计算机的可移植性。包括具有共享内存的计算机,如果为它们实现了 MPI。开发的代码也可以在工作站网络上执行,或者作为单个工作站上的多个进程执行。特别是,这使得在个人计算机上调试程序成为可能。

MPI 提供的另一种兼容性是在异构系统(具有不同架构的多个处理器)上透明工作的能力。在这种情况下,MPI 将自动执行数据转换并使用正确的通信协议(但是,对于异构架构,您必须使用 MPI 实现)。

MPI 的另一个重要优势是它的高效率,即使与“本地”系统相比也是如此。此外,对用户隐藏这个或那个操作是如何执行的,只有它做什么才是重要的。因此,MPI 可以很容易地在有和没有消息缓冲的系统上实现。各种实现可以利用多计算机的通信子系统,例如,通过让通信协处理器在其上执行协议的重要部分。

MPI 的效率也是通过不做不必要的工作来实现的,即在每条消息或编码-解码消息头中发送大量冗余信息。MPI 旨在支持同时执行计算和通信,以利用协处理器的存在。这是通过使用将通信的启动与终止分开的非阻塞通信调用来实现的。为了提高速度,MPI 使用了应用程序程序员通常根本不会考虑的技术。例如,内置缓冲允许您在发送数据时避免延迟 - 即使接收分支尚未准备好接收,控制也会立即返回发送分支。MPI使用多线程(multi-threading),通过将大部分工作转移到低优先级线程。缓冲和多线程将传输过程中不可避免的停机时间对应用程序性能的负面影响降至最低。一对多数据的传输所花费的时间不与所涉及的分支数量成正比,而是与该数量的对数成正比。等等...

可扩展性是并行处理的主要目标。MPI 允许或支持可伸缩性。

MPI 目标

开发人员为自己设定了以下任务:

  • 开发应用程序编程接口;
  • 实现通信效率(由于同时执行计算和通信,使用协处理器,拒绝从内存复制到内存);
  • 在异构环境中运行应用程序的能力;
  • 界面使用 Fortran 77 和 C 风格;此外,接口语义应该与语言无关;
  • 实现可靠的通信接口——用户不必处理通信中的错误;
  • 定义一个与已经使用的接口没有太大区别的接口,例如 PVM,并提供扩展以实现灵活性;
  • 定义一个可以在许多现有的多计算机上实现的接口,只需对系统软件进行少量更改。

平台

如前所述,使用 MPI 库编写的程序可以在具有分布式共享内存的多台计算机上、在工作站网络上、在这三种架构的任意组合上执行。

该接口可用于 MIMD 和 MPMD 程序(当每个进程在同一代码中遵循自己的路径,甚至执行自己的代码时)。它也可以用于 SPMD 程序。尽管没有对子流程的明确支持,但该接口旨在不干扰它们的使用。MPI 的下一个版本提供进程的动态生成。  

MPI 中包含的内容:

  • 进程-进程交互
  • 团队运作
  • 进程组
  • 通讯领域
  • 进程拓扑

不包括的内容:

  • 使用共享内存的显式操作
  • 需要更多操作系统支持的操作(远程执行)
  • 程序构建工具
  • 调试工具
  • 显式支持子流程
  • 任务管理支持
  • 输入输出功能

进程

MPI 程序由自治进程组成,这些进程以 MIMD 样式执行自己的代码(Fortran 77、C、C++)。每个进程执行的代码不必相同。不同的进程既可以在不同的处理器上运行,也可以在同一个处理器上运行——这对程序来说并不重要,因为在这两种情况下,数据交换机制是相同的。进程通过调用 MPI 原语进行通信。通常,每个进程都在自己的地址空间中运行,尽管共享内存的 MPI 实现是可能的。

MPI 没有定义每个进程的执行模型。一个进程可以是顺序的,也可以由可以并发运行的子进程组成。在这种情况下,阻塞 MPI 调用只会阻塞调用的子进程。

MPI 不提供用于确定进程在物理处理器上的初始分布的机制。这是由实施 MPI 的系统完成的。此外,MPI-1 标准不提供进程的动态生成和删除。

因此,进程以消息的形式相互交换数据。消息在允许程序和通信库相互区分的标识符下传递。为了联合执行某些计算,应用程序中的进程被组合成组。每个进程都可以找出它在组内的编号,并根据编号执行相应部分的计算。MPI 始终根据其组号(从 0 开始)识别进程。

MPI的特点:通信域的概念。启动应用程序时,所有进程都放置在为应用程序创建的公共连接区域中。如有必要,他们可以在现有连接区域的基础上创建新的连接区域。所有通信区域都有独立的进程编号(编号从 0 开始)。通讯器可供用户程序使用- 通信区域的描述符。许多 MPI 函数在其输入参数中都有一个通信器,这将它们的范围限制在它所附加的连接区域。一个通信区域可以有多个通信器。在这种情况下,应用程序使用这样一个连接区域,就像使用几个不同的区域一样。MPI 示例源通常使用标识符 MPI_COMM_WORLD。这是库自动创建的通信器的名称。它描述了通信的起始区域,它联合了应用程序的所有进程。

调用类型(函数) MPI

  • 本地(如果程序的完成只依赖于本地运行的进程);此类操作不需要与另一个用户进程进行显式交互。生成本地对象或查询本地对象状态的调用是本地的。
  • 非本地(如果程序的完成可能需要在另一个进程中执行某些 MPI 程序)。

换句话说,本地函数不会启动分支之间的数据传输。大多数信息函数都是局部的,因为 系统数据的副本已经存储在每个分支中。MPI_Send 发送函数和 MPI_Barrier 同步函数不是本地的,因为它们是转发的。应该注意的是,例如,接收函数 MPI_Recv(与 MPI_Send 配对)是本地的:它只是被动地等待数据到达,而不试图告诉其他分支任何事情。

  • 阻塞(如果返回值表示允许用户再次使用调用中定义的资源)。也就是说,阻塞函数会停止(阻塞)进程的执行,直到它们执行的操作完成。
  • 非阻塞(如果过程可以在调用发起的操作完成之前以及在允许用户再次使用调用中定义的资源(例如缓冲区)之前返回一个值)。非阻塞函数返回完成时取消的“请求”。在使用作为非阻塞函数参数的变量和数组清除收据之前,不要做任何事情。
  • 集体(如果通信者所描述的进程组中的所有进程都必须调用该函数)。

命名常量

MPI 程序有时会为参数分配特殊值。例如,标签是进程-进程交互操作的整数参数。它可以采用特殊值 MPI_ANY_TAG。

初始化表达式时可以使用所有命名常量。(不包括 - Fortran 中的 MPI_BOTTOM)。这些常量在执行期间不会改变它们的值。文档末尾有一个常量列表。  

风格

所有标识符都以“MPI_”前缀开头。这是一条规则,无一例外。不建议创建以该前缀开头的用户标识符,以及用于官方目的的前缀“MPID_”、“MPIR_”和“PMPI_”。

如果标识符由多个单词构成,则其中的单词用下划线分隔:MPI_Get_count、MPI_Comm_rank。但是,有时不使用分隔符:MPI_Sendrecv、MPI_Alltoall。

复合标识符中单词的顺序选择按照“从一般到特殊”的原则:先是“MPI_”前缀,然后是类别名称(Type、Comm、Group、Attr、Errhandler等),然后是名称操作(MPI_Erhandler_create,MPI_Erhandler_set,...)。最常用的函数不属于该方案:它们具有“反方法”但又短又刻板的名称,例如 MPI_Barrier 或 MPI_Unpack。

常量(和用户不能更改的变量)的名称用全大写字母书写:MPI_COMM_WORLD、MPI_FLOAT。在函数名中,前缀后的第一个字母是大写,其余都是小写:MPI_Send、MPI_Comm_size。

头文件 - mpi.h

几乎所有函数都返回错误代码。如果一切正常 - MPI_SUCCESS。有几个函数不返回此代码,因此它们可以作为宏执行。

数组参数从 0 开始编号。

0 - 假,非零 - 真

在描述 MPI 程序时,我们将使用 OUT 一词来指定“输出”参数,即 过程通过这些参数返回结果。  

未完待续~

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值