Open MPI 是一个开源的、高效的组件式结构 MPI 实现,它不仅为第三方研究者提供了一个稳定的平台,而且可以在运行时增加所需插件,具有较高的灵活性。
Open MPI 是由 LAM/MPI、LA-MPI、FT-MPI和 PACX-MPI的开发者们合作,并将这些 MPI 实现的特点融入到 Open MPI 中,开发出了这个基于组件结构的 MPI 实现。各个组件之间通过接口调用,实现组件的不同组合,提供对不同系统平台和不同通信互连结构的支持。Open MPI 作为一个开源的、产品级的MPI 实现,它的实现结构便于引入新的设计思想,可以采用新的设计方法和实现技术重新实现某一组件,而不会对其它组件产生影响。这种结构不仅为系统提供了一个稳定的基础通信平台,而且也为第三方研究者提供了一个灵活强大的研究平台。为了保证通用性,Open MPI 实现了 MPI-1 和 MPI-2 标准并支持多线程应用(例如,MPI_THREAD_MULTIPLE)。
OpenMPI 中实现了大量的功能组件,其中 SM(shared memory)组件是 Open MPI 专门为结点内通信所设计的消息传递组件。SM 组件在结点内建立共享内存,进程之间的消息传递就是通过共享内存来完成的,即发送进程将消息拷贝到共享内存,再由接收进程从共享内存中将消息拷出;SM 组件在 Open MPI 所有消息传递组件中具有较高的优先级,当一个进程可以通过 SM 组件与另一进程通信时将会优先使用 SM 组件。对于短消息的传递,SM 组件具有较好的性能;但是对于长消息的传递,由于共享内存的消息传递方式需要执行两次内存拷贝操作,当消息较长时,拷贝开销会增大,因此会对消息传递性能产生较大影响。
Open MPI 主要由三层组成:OMPI(Open MPI)、ORTE(Open Runtime Environment)、OPAL(Open Portability Access Layer)。OMPI 层主要提供对 MPI的接口以及辅助逻辑;ORTE 层提供与后台运行系统的接口;OPAL 层则负责与操作系统的交互。
其中OMPI、ORTE和OPAL每层都有一个独立的MCA(Modular Component Architecture),MCA 内是组件框架(Framework)、组件框架下就是隶属于该框架的组件(也称 模块)(Component)
作为组件结构的核心,MCA 为其他层提供管理服务。例如,可以接收来自mpirun 运行时的参数并通过组件框架将其传递给某个组件;而且 MCA 还可以在编译时自动寻找组件,并调用相应的 hook 来进行配置、编译和安装。 MCA 内是组件框架,每个组件框架用于完成某一项任务,例如提供并行作业的控制或执行 MPI 聚合通信;同时根据任务的需要,组件框架将对相应组件进行搜索、加载、使用和卸载;每个框架都有不同的策略和使用场合,有的在一次任务中只使用一个组件,而有的则同时使用所有可用组件。
组件框架内就是该类的各种组件,它们都是独立的软件单元且拥有明确定义的接口,可独立使用也可与其他组件组合。Open MPI 为运行时组件的选择和参数的传递提供了多种机制,包括在 mpirun 的命令行使用参数、修改环境变量、编辑文本文件和使用 MPI 属性(例如,选择消息传递组件)。
以 OMPI 层为例,其 MCA 下包含的组件框架有 PML(Point-to-point Management Layer)、BML(BTL Management Layer)、MPool(Memory Pool)、BTL(Byte-Transfer-Layer Layer)等。
PML 组件框架负责管理所有消息的传递,实现了 MPI 点点通信原语,包括标准、缓冲、准备和同步四种通信模式。PML 根据具体的调度策略对 MPI 消息进行调度,该策略是根据 BTL 的具体属性决定的。短消息传递协议和长消息传递协议也是在 PML 中实现的。所有控制信息(ACK/NACK/MATCH)也都由 PML 进行管理。这种结构的优点是将传输协议从底层互连中分离出来,显著的降低了代码的复杂度和冗余度,增强了可维护性。
BML 组件框架为任务启动和动态进程的创建提供搜索和维持负责点点通信的BTL 组件的服务。BML 可以协调结点资源,并为 BTL 的使用者进行缓冲,当发现资源后,其他层会绕过 BML 组件框架直接与 BTL 通信,提高了通信性能。
MPool 内存池提供内存分配/释放和注册和注销服务。对于 Infiniband 和 Myrinet等都需要在发送/接收或 RDMA 操作之前注册内存(使物理内存页锁定)才能将内存作为源或者目标来使用。将这个功能从其他组件中分离出来可以使 MPool 被更多的组件框架或组件共享。
BTL 组件框架负责处理所有点对点消息传送,包含了一组用于发送/接收或RDMA 的通信组件单元。BTL 不受 MPI 语义的影响,它仅仅是通过最基本的传递功能来在进程间进行数据交换(包括连续的和非连续的数据)。这样的组件框架为网络设备的开发商提供了便利,同时也可以支持更广泛的结点间通信设备。
Open MPI 的组件结构为用户和库开发者提供了许多优势。首先,它允许在一个 MPI 任务中使用多个组件,例如在多个进程间通信时,如果两个进程位于不同结点上并且所有 BTL 的组件可用,结点之间网络设备使用的是 Infiniband,那么在结点间进程之间是通过使用 BTL 组件框架中的 OpenIB 组件进行通信,而在结点内则使用 SM 组件进行通信,从而利用组件的特点来提高消息传递的性能;其次,它为使用第三方软件提供了便利条件,支持组件的源代码或软件包形式;最后,它提供了一个细粒度、运行级、用户控制的组件选择机制。
下面以 BTL 组件框架为例介绍执行 MPI 任务时 BTL 的工作过程:
首先,在 MPI 初始化时,BML 组件框架搜索所有可用的 BTL 组件,这些组件可以被静态的连接到 MPI 库中,也可以将其从共享库中加载;然后 BML 询问每个 BTL 组件是否需要在进程中运行,例如如果没有可用的 Infiniband 网络设备,就可以选择不运行基于 Infiniband 的组件;组件选择并初始化后,将返回给 BML一组 BTL 框架下的组件列表,每个组件代表不同的网络接口或端口,负责缓冲资源并处理底层传输通信所需信息;BML 对这些 BTL 组件进行轮询,以确定每个组件所对应的通信结点并且保留一份列表,这个列表对于上层 PML 组件框架是透明的,这样可以实现高效的消息分发和分割;这些 BTL 组件在进程的生存周期内存在,当 MPI 结束时每个 BTL 组件在关闭之前清理所有分配的资源。