第2章 MPI术语与约定 MPI Terms and Conventions
这一章节解释了MPI文档中使用的符号术语和惯例,以及其中所做的一些选择和背后的原因。
2.1 文档符号表示 Document Notation
Rational. 在整个文档中,对界面规范中所做设计选择的理由以这个格式(首尾包裹)进行标注。某些读者可能希望跳过这些部分,而对界面设计感兴趣的读者可能会仔细阅读它们。(End of advice to Rational.)
Rationale. (End of rationale.)
Advice to users. 在整个文档中,针对用户并且展示用法的材料以这个格式(首尾包裹)进行标注。某些读者可能希望跳过这些部分,而对MPI编程感兴趣的读者可能会仔细阅读它们。(End of advice to users.)
Advice to users. (End of advice to users.)
Advice to implementors. 在整个文档中,主要针对实现者的评论性材料以这个格式(首尾包裹)进行标注。某些读者可能希望跳过这些部分,而对MPI实现感兴趣的读者可能会仔细阅读它们。(End of advice to implementors.)
Advice to implementors. (End of advice to implementors.)
2.2 命名约定
在许多情况下,C函数的MPI名称的形式为MPI_Class_action_subset。这种约定起源于MPI-1。从MPI-2开始,尝试根据以下规则对MPI函数的名称进行标准化。
- 在C和Fortran的mpi_f08模块中,与特定类型的MPI对象相关联的所有例程应该采用
MPI_Class_action_subset
的形式,如果不存在子集,则采用MPI_Class_action
的形式。在Fortran的mpi模块和(已弃用的)mpif.h文件中,与特定类型的MPI对象相关联的所有例程应该采用MPI_CLASS_ACTION_SUBSET
的形式,如果不存在子集,则采用MPI_CLASS_ACTION
的形式。 - 如果例程与类无关,则名称应采用
MPI_Action_subset
或MPI_ACTION_SUBSET
的形式,在C和Fortran中均适用。 - 某些动作的名称已经标准化。特别地,create表示创建一个新对象,get表示获取关于对象的信息,set表示设置这些信息,delete表示删除信息,is表示询问对象是否具有某种属性。
MPI-1过程中定义的一些MPI函数的C和Fortran名称在几种情况下违反了这些规则。最常见的例外是省略了例程中的Class名称,以及在可以推断出的情况下省略了Action。
2.3 程序规范
MPI 程序使用一种与语言无关的符号表示法进行规范,过程调用的参数被标记为 IN、OUT 或 INOUT。它们的含义如下:
IN:程序调用可以使用输入值,但在调用执行期间不会从调用者的角度更新参数,
OUT:程序调用可以更新参数,但不使用其输入值,
INOUT:程序调用可以同时使用和更新参数。
特殊情况是,如果参数是一个不透明对象的句柄(这些术语在第2.5.1节中有定义),并且该对象在过程调用中被更新,则该参数标记为INOUT或OUT。即使句柄本身没有被修改,我们也使用INOUT或OUT属性来表示句柄所引用的内容被更新了。
Rationale. MPI的定义尽可能避免使用INOUT参数,因为这种使用方式容易出错,特别是对于标量参数而言。 (End of rationale.)
MPI对IN、OUT和INOUT的使用旨在告知用户如何使用参数,但并没有提供一个严格的分类,可以直接转换为所有语言绑定(例如,Fortran 90绑定中的INTENT或C绑定中的const)。例如,“常量”MPI_BOTTOM
通常可以传递给OUT缓冲区参数。类似地,MPI_STATUS_IGNORE
可以作为OUT状态参数传递。
MPI函数中常见的一种情况是一个参数在某些进程中用作IN,在其他进程中用作OUT。这样的参数在语法上是一个INOUT参数,并被标记为这样,尽管在语义上,在单个进程中它不会在一次调用中同时用于输入和输出。
另一个常见情况是当某些进程只需要某个参数值时,当参数在某个进程中不重要时,可以传递任意值作为参数。
除非另有说明,类型为OUT或INOUT的参数不能与传递给MPI过程的任何其他参数别名。下面是一个C中参数别名的示例。如果我们定义一个C过程如下所示,
void copyIntBuffer ( int *pin, int *pout, int len)
{ int i;
for (i=0; i<len; ++i) *pout++ = *pin++;
}
以下代码片段中对它的调用存在参数别名。
int a [10];
copyIntBuffer (a, a+3, 7);
C语言允许这样使用,但MPI过程的这种用法是禁止的,除非另有规定。请注意,Fortran禁止参数的别名使用。 所有MPI函数首先以与语言无关的符号表示进行规定。紧随其后是语言相关的绑定:
- ISO C版本的函数。
- 与USE mpi_f08一起使用的Fortran版本。
- 使用USE mpi或(已弃用的)INCLUDE 'mpif.h’的相同函数的Fortran版本。
一些MPI过程为特定语言支持提供了两个接口;参见第2.5.6节和第2.5.8节。
一个例外是第15.3节“MPI工具信息接口”,该节仅提供ISO C接口。
此文档中的“Fortran”指的是Fortran 90或更高版本;请参阅第2.6节。
在本标准中,词语“函数function”、“例程routine”、“过程procedure”、“过程调用procedure call”和“调用call”通常被用作同义词。
2.4 Semantic Terms
在讨论MPI过程时,使用以下语义术语。术语"message data buffer"指的是通信过程中使用的发送/接收缓冲区。术语"file data buffer"指的是MPI I/O过程中使用的数据缓冲区。在本节中,我们使用术语"data buffer",具体指的是消息数据缓冲区还是文件数据缓冲区取决于MPI过程。附录A.2显示了本节中定义的术语如何适用于所有与操作相关的MPI过程。
2.4.1 MPI操作
MPI操作:MPI操作是由MPI库执行的一系列步骤,用于建立和启用数据传输和/或同步。它包括四个阶段:初始化、启动、完成和释放,并且实现为一组一个或多个MPI过程,详见第2.4.2节。
- 初始化initialization:将参数列表传递给操作,但不传递数据缓冲区的内容(如果有)。操作的规范可能规定,在操作被释放之前,数组参数不得更改。
- 启动Starting:将数据缓冲区(如果有)的控制权交给关联的操作。请注意,启动initiation指的是初始化initialization和启动starting阶段的组合。
- 完成:返回数据缓冲区的内容的控制权,并指示已更新输出缓冲区和参数(如果有)。 请注意,当实现完成阶段的MPI过程返回时,MPI操作已完成。
- 释放:返回剩余参数列表的控制权(例如,数据缓冲区地址和数组参数)。
MPI操作可以以阻塞、非阻塞和持久化的形式之一或多个形式提供。
-
阻塞操作:对于阻塞操作,所有四个阶段都在单个过程调用中组合(如图2.1所示,并在第2.4.2节中定义)。
-
非阻塞操作:对于非阻塞操作,初始化和启动阶段合并为单个非阻塞过程调用,完成和释放阶段合并为单独的、单个过程调用,可以是阻塞的也可以是非阻塞的(如图2.2所示,并在第2.4.2节中定义)。
-
持久化操作:对于持久化操作,每个阶段都有单独的过程(如图2.3所示,并在第2.4.2节中定义)。每个过程可以是阻塞的也可以是非阻塞的。
对于分区发送操作,需要额外调用每个分区的发送缓冲区以完成启动阶段(参见第4.2.1节)。对于分区接收操作,在操作完成之前,用户可以在验证已经到达后访问输出缓冲区的分区(参见第4.2.2节)。
这四个阶段导致了操作状态的初始化、启动、完成和释放。启动的(started)操作也称为活动的(active),而初始化和完成状态也称为非活动的(inactive)。
活动的(active)通信和I/O操作也称为待处理的(pending)操作。请注意,待处理的操作可以是已开始但尚未完成(即使请求句柄已被释放)的非阻塞或持续操作,也可以是尚未完成的阻塞操作,例如等待接收消息的接收操作。
MPI操作还可以是集合的collective或非集合的noncollective。
-
集合操作:一组相关操作,每个MPI进程在一个组或多个MPI进程的组中执行一个操作。对于集合操作,完成阶段可能在组中的所有进程开始操作之前完成,也可能不会。 集合MPI操作也可以作为阻塞、非阻塞或持久操作提供。
-
非集合操作:非集合noncollective操作被定义为not collective操作。
许多MPI操作需要在多个MPI进程中协调活动:这种操作的语义要求在操作转换到完全操作状态之前,必须启动一个或多个其他特定的语义相关操作。例如,接收操作需要在接收完成之前启动一个相关的发送操作;或者一个集体操作在所有相应组的MPI进程中启动这些操作之前可能不会完成。
- Enabled: 当在特定的MPI进程中启动了所有特定语义相关的操作以确保在该MPI进程中完成时,MPI操作就处于启用状态。
Rationale. MPI实现可以包含优化(例如自动缓冲),允许MPI操作在启用之前完成。(End of rationale.)
有些MPI操作是事先启用的(priori enabled),即它们不需要任何其他特定语义相关的操作来完成。例如,一个带缓冲的发送操作可以独立于相关的接收操作而完成。
一旦MPI操作被启用,该操作必须最终完成。一个操作在启动之前可能已经被启用。例如,如果一个接收操作在匹配的发送操作启动之后启动,则该接收操作已经被启用。
Rationale.
操作A的enabled的定义是不对称的:enabled包括所有特定的语义相关操作
A
i
′
A^′_i
Ai′已经开始以确保完成,但不包括操作A本身已经开始。
示例:
- 当相关的发送操作已经开始时,receive被启用。
- 标准模式send在相关的receive已经开始时被启用。如果MPI实现选择使用内部缓冲区,则send操作可能在启用之前已经完成,即receive操作已经开始。
- 同步模式的send操作在相关的receive操作已经开始时被启用,并且在启用之前不能完成。
- 缓冲(buffered)模式的send操作是事先启用的。
- 就绪(ready)模式的send操作只有在已经启用时才能开始,即相关的receive操作已经开始。
- 对于集合的广播,特定MPI进程上的操作仅在组中所有其他MPI进程已经开始相关广播操作时才被启用。
具体地说,对于构成可能同步的集体操作的一组MPI进程上的相关操作,对于特定MPI进程p上的操作,当组中所有其他MPI进程pi != p已经开始其相关操作时,该操作被启用,而p上的操作不必已经开始。
(End of rationale.)