11.1 替代的外部模型:LOCAL和SERIAL BACKWARD FORWARD


一个全局HPF程序可被看作是基于程序控制的单一逻辑线索,松同步方式下的一组处理器间的合作。第五节定义了可从全局HPF中调用的另外两个模型:LOCAL,该模型是单处理器“节点”代码,其中所有的活动处理器都参与运行,但是只有那些映射到给定物理处理器上的数据可被直接访问,而SERIAL模型则是单处理器,单独操作,在SERIAL子程序被调用前,由调用者将所有必要的数据都聚集在一起。作为使用例子,LOCAL模型对于用显式消息传递代码书写数据通信程序很有用,而SERIAL模型可被用于调用系统库或特殊的I/O例程。

LOCAL和SERIAL模型都能从全局HPF程序中调用,但一般来说,这些模型不能混合使用。没有定义从LOCAL或SERIAL中调用GLOBAL HPF。进一步讲,也没有定义从LOCAL中调用SERIAL。5.3.1节中给出了不同模型之间怎样相互作用的更多的细节。

从全局HPF调用的所有LOCAL和SERIAL子程序都必须满足一些附加的约束:

LOCAL和SERIAL子程序中I/O语句的行为是依赖于实现的。

11.1.1 LOCAL模型

可通过指定在每个处理器上运行的局部过程代码将一个外部过程定义为显式SPMD代码。在本节中,我们描述了调用者和一个本地被调过程间的协议。一个很重要的问题是不要将外部过程和本地过程混淆,前者概念上是一个从HPF程序中调用的过程实体,而后者则是在每个节点上运行,每个节点一个过程。引用一个外部过程将导致在每个处理器上各自引用本地过程。外部过程的执行包含了每个执行处理器上本地过程的并发执行。每个本地过程可在任意时刻通过执行RETURN语句终止。但是,仅当每个本地过程都终止了,外部过程才能在总体上终止;实际上,在返回全局HPF调用者之前,处理器需要同步。

除了从本地过程返回到初始化本地执行的全局调用者之外,本地执行处理器不需要任何隐式同步。本地过程可使用任何控制结构。为访问处理器之外的数据需要或者在运行本地代码前进行预备通信以便将数据拷贝到处理器中,或者在本地过程各自执行的拷贝之间进行通信。个别的实现可以为通信提供依赖于实现的方式,例如通过消息传递库或共享存储机制。这种通信超出了这个说明的范围。但是注意,许多仅要求独立于控制结构的有用的方便算法可以利用本地例程,而无须要求一种通信机制。

本地模型仅假定非顺序数组维分别映射到矩形处理器网格的各维上,每个数组维至多映射到一个处理器维上(无扭曲分配)且没有两个数组维映射到同一处理器维上。这一约束充分保证了每个物理处理器都包含可在一个矩形结构中被本地排列的数组元素的一个子集。(当然,为计算一个给定本地索引元素的全局索引,或者相反,可能是一个很复杂的计算—但是是可能的。)在CYCLIC分配中,数组的多个区域可被映射到本地处理器上。

如果在任何实现中接口类没有遵循本节所描述的惯例,则建议该接口类的名字不要使用LOCAL关键字作为模型的名字。

11.1.1.1 调用本地子程序的惯例

标量哑参,标量函数结果以及顺序数组的缺省映射这样的:将参数在每个物理处理器上重复。这些映射在接口中可选择为显式的(除了顺序数组的情况之外,该数组不能显式映射),但是任意其它的显式映射都不符合HPF标准。哑参不能是显式映射的派生类型或具有显式映射结构的部件。

与非外部子程序中一样,实参可以以任意方式映射;如果必要的话,在引用外部过程前以及从外部过程返回后,将它们自动拷贝到正确映射的临时单元中。

应该注意,调用本地子程序的惯例仅适用于全局和本地模型间的接口。这些惯例不能进一步传播给本地模型中所调用的子程序。

11.1.1.2 调用顺序

下面的动作细节必须发生在每个处理器上引用本地过程之前。调用例程的编译器强制这些动作发生,程序员不负责这些动作,它们也不会与本地过程冲突。

  1. 处理器之间进行同步。另外,逻辑上在调用之前的所有动作都已完成。
  2. 根据外部过程所定义接口中的指令(显式的或隐式的),如果有必要可对每个实参进行重映射。这样,出现在接口中的HPF映射指令是捆绑的——编译器在调用本地外部过程时必须遵循这些指令。(这一规则的原因是数据映射在本地例程中是显式可见的。)对应于顺序数组和标量哑参的实参在所有的处理器上重复(例如通过广播)。具有显式映射结构部件的派生类型标量或显式映射派生类型标量不能从全局HPF中传给外部本地过程。
  3. 如果被调过程所访问到的一个变量具有重复描述,则根据源程序的顺序语义在调用前对所有的拷贝进行更新以便包含正确的当前值。

在这些动作都发生后,在每个处理器上引用本地过程。下面的11.1.1.3节描述了本地引用所获得信息。

下列动作发生在控制转移回调用者之前。

  1. 调用后所有处理器进行同步。另外,本地例程每个拷贝的执行完成于调用者重新执行之前。
  2. 如果有必要,重新存储参数的原始分配(以及外部函数结果的原始分配)。

对实现者的建议:在从子程序返回前,实现时可以进行检查以确保重复变量已被子程序一致性更新。但是,当然不要求——或者甚至一点也不鼓励——这么做。由本地子程序的负责这么做,同时调用者中的检查是速度和可维护性之间的一个折衷。(对实现者的建议结束)

11.1.1.3 本地过程可利用的信息

每个处理器上引用的本地过程传递一个本地参数用作调用者所传递的每个全局参数,并传递给(全局)外部过程接口。每个全局参数都是一个HPF数组或标量。相应的本地参数是存储在本地的全局数组的一部分,或者是标量参数的一个本地拷贝或者是跨处理器重复的顺序数组。注意,如果HPF数组是重复的,则每个本地过程接收整个实参的一个拷贝。HPF调用者所传递的数组实参称为一个全局数组;全局数组传递给本地例程一个拷贝的子网格成为一个局部数组。

如果外部过程时一个函数,则本地过程也是一个函数。该函数的每个本地引用将返回外部函数返回值的本地部分。仅允许标量值的外部函数。所有本地函数必须返回相同的值。

如果一个全局HPF程序用实数组参数X调用本地子程序A,且A接收数组X的一部分作为哑参P,则A可以调用另外的本地子程序B并将P或P的一个区域作为实参传给B。

运行时接口必须为每个本地参数提供每个本地函数可以发现的相应全局参数的足够的映射信息,将全局索引翻译成本地索引,反之亦然。11.7.1节的HPF LOCAL库中列出了提供这一信息的一组专门的过程。本地例程利用这一信息的方式依赖于实现和本地例程所使用的程序设计语言。

11.1.2 SERIAL模型

本节定义了一组惯例,在该惯例下所书写的代码中,子程序一个实例的执行仅在一个处理器上。

如果程序单元具有外部模型SERIAL,HPF编译器应假定子程序被编码成在一个单处理器上运行。从全局HPF调用者的角度,SERIAL过程的动作与同一代码的HPF过程是相同的。差别可能仅在于不同的实现行为(例如性能)。

现在还没有一种方式来指定哪个处理器执行一个HPF_SERIAL过程。

11.1.2.1 串行调用顺序

从全局HPF中调用一个SERIAL过程前,程序的行为就好象下列动作发生:

  1. 处理器间进行同步。逻辑上在调用之前的所有动作都完成。
  2. 所有实参被重映射到实际执行SERIAL过程的处理器上。每个参数对于SERIAL过程都以一个顺序参数出现。

SERIAL过程的行为就好象它仅在一个处理器上执行。当从全局HPF中引用的SERIAL过程实例完成后,则发生如下动作:

  1. 调用后所有处理器进行同步。
  2. 重新存储实参的原始映射。

BACKWARD FORWARD