3.4 通信模式 |
在3.2.1节描述的发送调用是阻塞的: 它直到消息数据和信封已被安全取出和存储才返回以便发送者自由存取和重写发送缓存。消息可能被直接拷贝到匹配的接收缓存,或被拷贝到一个暂时的系统缓存。
消息缓存退耦发送和接收操作。只要消息被缓存起来,既使接收者没有执行匹配接收,一个阻塞发送能完成。另一方面,消息缓存是昂贵的,因为它承担附加的存储器到存储器拷贝,而且它要求为缓存分配存储空间。MPI提供几个通信模式选择, 使你控制通信协议的选择。
在3.2.1节描述的发送调用使用标准的通信模式。在这种模式中,由MPI决定正在出发的消息是否被缓存。MPI可以缓存正出发的消息。这时,在引用一个匹配接收以前,发送调用可以完成。另一方面,缓存空间可以得不到,或因性能原因, MPI可以选择不缓存正出发的消息。这时,发送调用直到一个匹配接收登入并且数据被移入接收者才完成。
所以,无论一个匹配接收是否登入,一个标准模式的发送能开始。它可以在匹配接收登入以前完成。标准模式的发送是非局部的:发送操作成功的完成依赖于一个匹配接收的发生。
基本原理. MPI不愿规定标准发送是否是缓存的原因是希望达到可移植性程序。因为虽着消息尺寸的增大, 任何系统将用完缓存资源, 有些实现想提供较少的缓存,在标准模式下, MPI负责使程序不依赖系统缓存。缓存可以提高一个正确程序的性能,但它不影响程序的结果。如果用户希望保证一定数量的缓存,可以使用3.6节提供的缓存系统, 和缓存模式发送。(基本原理结束)。
有三个附加的通信模式。
无论一个匹配接收是否已登入,能够开始一个“缓存模式”的发送操作。它可以在一个匹配接收登入已前完成。但是,不象标准发送,这个操作是局部的,它的完成不依赖一个匹配接收的发生。因此,如果执行一个发送而没有匹配接收登入,那么MPI必须缓存正出发的消息, 以便允许发送调用完成。如果没有充足的缓存空间,一个错误将发生。可得到的缓存空间数量由用户控制--看3.6节。为使缓存模式有效可以要求用户分配缓存。
无论一个匹配接收是否登入,能开始“同步模式”的一个发送操作。但是,只有一个匹配接收登入,接收操作已开始接收同步发送的消息时,发送操作将成功完成。所以,一个同步发送的完成不表示发送缓存能被再使用,但是表明接收者已到达执行的某一点,即它已开始执行匹配接收。如果发送和接收都是阻塞操作,那么同步模式的使用提供同步语义:两个进程在通信时聚会以前,一个通信不能完成。在这个模式下执行的一个发送是非局部的。
只要匹配接收已登入,可以开始一个“准备好通信”模式的发送。否则,这个操作是错误的,其结果是无定义的。在某些系统,这允许移出一个信号交换式操作,并导致提高性能。发送操作的完成不依赖一个匹配接收的状态,只表明发送缓存能被再使用。准备好模式的一个发送操作,与一个标准发送操作或一个同步发送操作有相同的语义;只是发送者给系统提供附加的信息( 即:一个匹配接收已登入 ),能节省一些额外开销。因此,在一个正确的程序中,一个准备好发送能被一个标准发送替代,对程序的动作无影响而对性能有影响。
为三个附加的通信模式提供三个附加的发送函数。由一个字母前缀表示通信模式:B 用于“缓存模式”,S 用于“同步模式”,R 用于“准备好模式”。
MPI_BSEND(buf, count, datatype, dest, tag, comm)
IN buf 发送缓存的初始地址(选择型)
IN count 发送缓存中元素的个数(整型)
IN datatype 每个发送缓存元素的数据类型(句柄)
IN dest 目标进程号(整型)
IN tag 消息标志(整型)
IN comm 通信子(句柄)
int MPI_Bsend(void* buf, int count, MPI_Datatype datatype, int dest,
int tag, MPI_Comm comm) MPI_BSEND(BUF, COUNT, DATATYPE, DEST, TAG, COMM,
IERROR)
<type>BUF(*)
INTEGER COUNT, DATATYPE, DEST, TAG, COMM, IERROR
以缓存模式发送。
MPI_SSEND(buf, count, datatype, dest, tag, comm)
IN buf 发送缓存的初始地址(选择型)
IN count 发送缓存中元素的个数(整型)
IN datatype 每个发送缓存元素的数据类型(句柄)
IN dest 目标进程号(整型)
IN tag 消息标识(整型)
IN comm 通信子(句柄)
int MPI_Ssend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)
MPI_SSEND(BUF, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
<type> BUF(*)
INTEGER COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
以同步模式发送。
MPI_RSEND(buf, count, datatype, dest, tag, comm)
IN buf 发送缓存的初始地址(选择型)
IN count 发送缓存中元素的个数(整型)
IN datatype 每个发送缓存元素的数据类型(句柄)
IN dest 目标进程号(整型)
IN tag 消息标识(整型)
IN comm 通信子(句柄)
int MPI_Rsend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)
MPI_RSEND(BUF, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
<type>BUF(*)
INTEGER COUNT, DATATYPE, DEST, TAG, COMM, IERROR
以准备好模式发送。
只有一个接收操作,能和任何发送操作模式匹配。在上节描述的接收操作是阻塞的:只有接收缓存包含新接收消息时, 它返回。在匹配的发送已完成以前,一个接收能完成( 当然, 只在匹配发送已开始后, 它能完成。)
在MPI的多线索实现中, 系统可以再调度一个阻塞发送或接收操作的线索, 并调度在同一地址执行的另一线索。这时,到通信完成时,用户才负责存取或修改一个通信缓存。否则,计算的结果是无定义的。
基本原理. 当一个发送缓存正在被使用时, 我们禁止读取这个发送缓存, 既使这个发送操作可能不改变这个缓存的内容。这似乎比要求的更严格,但在某些系统,这可减少功能损失,并允许高性能--考虑由DMA发动完成的数据转换情况,DMA发动是和主处理器非紧耦的高缓存。(基本原理结束)。
给实现者的建议. 因为在一个匹配接收登入以前, 一个同步发送不能完成, 所以你将不能正常暂存这样操作发送的消息。
只要可能,为标准发送在阻塞发送者上,选择缓存。编程者通过使用同步发送模式,在一个匹配接收发生以前能为阻塞发送者发优选信号。
下面概述各种通信模式的一个可能的通信协议。
ready send(准备好发送): 只要一可能, 消息就被发送。
synchronous send(同步发送): 发送者发一个“请求发送”的消息。接收者存储这个请求。当一个匹配接收登入时,接收者发回一个“允许发送”的消息,这时接收者发送消息。
standard send: 第一个协议用于短的消息, 第二个协议用于长的消息。
buffered send: 发送者把消息拷贝到一个缓存, 然后以非阻塞方式发送它(使用与标准发送同样的协议)
为了流控制和错误发现, 需要附加的控制信息。当然,有许多其他可能的协议。
准备好发送被作为一个标准发送被实现。这时,准备好发送没有优点(或缺点)。
一个标准发送能作为一个同步发送被实现。这时,不需要数据缓存。但是,许多(大多数?)用户希望一些缓存。
在多线索环境, 一个阻塞通信的执行只阻塞执行线索, 允许线索调度器再调度这个线索并调度另一个执行线索。(给用户的建议结束)。
Copyright: NPACT |