通讯: 点对点
MPI的通讯是指程序在不同的处理器之间进行数据交换的一种行为,通讯方式按照目标的不同主要分为两类:点对点通讯和集群通讯。 点对点通讯需要一个处理器进行发送,另外一个处理器进行接收。
Message
要了解MPI的通讯,首先需要了解一下MPI中Message的结构。Message主要包含数据(3个参数),封包(3个参数)以及其他的一些与通讯有关的参数
其中,数据主要包括:
- 数据指针(datapointer): 数据或数组的第一个元素的地址;
- 数据长度(count): 当前类型元素的个数(注意,不一定是数组元素个数,尤其是使用自定义类型时);
- 数据类型(datatype): 数据类型(可以是内置类型(如MPI_INT,MPI_DOUBLE),也可以是自定义类型(Derived Data Type))。
封包:
- 通讯目标(dest): 目标处理器的rank,当目标不确定时可以使用MPI_ANY_SOURCE;
- 封包标志(tag): 用于标识Message,只有具有相同tag的发送和接收函数才能进行通讯;
- 通讯器(communicator): 当前通讯的系统,MPI中默认的通讯系统为MPI_COMM_WORLD。但多数情况下会根据传输方向和内容自定义一些子系统,尤其是在集群通讯中。
Message中通常还会带有关于通讯状态的结构体变量:
MPI_Status。 它包含了三个重要成员:
- MPI_SOURCE: Message源在当前通讯系统中的rank;
- MPI_TAG: 通讯标识;
- MPI_ERROR: 通讯中的错误信息。
这些参数都可以用
.运算取得,有了这些参数在任何情况下,处理器都能清楚的知道数据发送源的信息。
Send
点对点通讯共有八种发送方式,包括四种阻塞式发送(blocking)
MPI_Send,
MPI_Ssend,
MPI_Rsend,
MPI_Bsend和四种非阻塞式(non-blocking)
MPI_Isend,
MPI_Issend,
MPI_Irsend,
MPI_Ibsend。阻塞式发送是指在发送指令执行后到数据传输结束之前,当前处理器处于阻塞状态,不会进行任何其他的运算。相对的,非阻塞模式则是在传输过程中,处理器还可以进行其他运算,因此需要额外的函数判断通讯是否结束,例如
MPI_Test 和
MPI_Wait。 MPI的Send函数调用方式通常为:
MPI_Send(datapointer, count, datatype, dest, tag, comm); MPI_Isend(datapointer, count, datatype, dest, tag, comm, request);
此外,还可以按照发送类型把他们分成如下四类:
- 标准型(Standard):MPI_Send和MPI_Isend,最基本的发送类型,会根据数据大小选择不同的发送方式。当数据长度小于规定阈值时,采用缓冲型;当数据较大时采用同步型。
- 同步型(Synchronous):MPI_Ssend和MPI_Issend,需要先进行握手,建立链接后进行发送。
- 立即型(Ready):MPI_Rsend和MPI_Irsend,不需要预先握手,只要有相关的接收命令,就可以发送。
- 缓冲型(Buffer):MPI_Bsend和MPI_Ibsend,需要用户通过MPI_Buffer_attach(buffer, buflen);手动创建一个缓冲区,而后将数据通过MPI_Bsend(data,count,type,dest,tag,comm);将数据发送到缓冲区,系统会在完成握手后自动将缓冲区中的数据发送出去。
这是一段完整的使用缓冲型发