OpenMPI 学习笔记(三)点对点通信
一、原理
所谓的点对点通信发生在两个过程之间:发射器和接收器(或接收器)。
发射器和接收器通过它们在通信器中的等级来识别。
发送的消息包括:
- 沟通者(必须包含两个进程)
- 发送者的等级,
- 接收者的等级,
- 消息的标签(标识符)。
- 报告的数据类型必须指定。
- 有几种传输模式。
二、例子
int MPI_Ssend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm); int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status);
comm : 沟通器
tag : 信息标签
dest/source : 在该沟通器中的发送者和接受者的等级号
datatype : 所发送的数据的类型
count :发送和接受的数据数量
buf : 发送/接收的数据的开始地址
// intro/send-receive.c #include <mpi.h> #include <stdio.h> int main(int argc, char** argv) { MPI_Init(&argc, &argv); int wrank; MPI_Comm_rank(MPI_COMM_WORLD, &wrank); int witness = 0; if (wrank==2) { int modifier = 1; MPI_Ssend(&modifier, 1, MPI_INT, 3, 28, MPI_COMM_WORLD); } else if (wrank==3) MPI_Recv(&witness, 1, MPI_INT, 2, 28, MPI_COMM_WORLD, MPI_STATUS_IGNORE); printf("Rang %d, witness %d.\n", wrank, witness); MPI_Finalize(); return 0; }
上面执行的是:进程2发给进程3一个int型数字 :1
在控制台测试:
$ mpirun -n 4 source
Rang 1, witness 0.
Rang 0, witness 0.
Rang 2, witness 0.
Rang 3, witness 1.
上面演示的是传递一个值,下面我们看传递多个值的情况:
// intro/send-receive.c int witness[] = {0, 0}; if (wrank==2) { int modifier[] = {1, 1}; MPI_Ssend(modifier, 2, MPI_INT, 3, 28, MPI_COMM_WORLD); } else if (wrank==3) MPI_Recv(witness, 2, MPI_INT, 2, 28, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
对于所有通信,须指定通信类型(MPI有很多种通信类型),而且发送者和接受者的类型应当配套使用:
MPI_Ssend的标签必须与MPI_Recv的标签匹配,否则通信失败。
数据传输是用一个简单的字节完成的(类型中没有数据)。
由程序员来验证发送和接收的类型是相同的,或者至少它们是兼容的(参见示例框架153和158)
⚠️注
如果发送的字节数等于接收的字节数,通信将成功。例如,可以发送一个包含两个int的数组,并接收一个long或者一个double。
三、有关标签的详细信息
标记必须是介于0和系统相关值之间的整数,系统相关值由以下程序获取。该最大值总是≥32767。
// tag.c #include <mpi.h> #include <stdio.h> int main(int argc, char** argv) {
MPI_Init(&argc, &argv); int flag; int* max_tag;
MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_TAG_UB, &max_tag, &flag); printf("Maximum tag : %d.\n", *max_tag); MPI_Finalize(); return 0; }
多个进程重复使用相同的标签不是一个问题:无论通信的模式如何,接收顺序与发送顺序相同。
待解决:
À la réception d'un message, le rang de l'émetteur et l'étiquette peuvent être des jokers , respectivement MPI_ANY_SOURCE etMPI_ANY_TAG.
收到消息后,发送方的等级和标签分别可以是“jokers”MPI_ANY_SOURCE和MPI_ANY_TAG。
四、基本数据类型
所有MPI_ *类型的大小均为8个字节。
⚠️补充说明:
只有收到指定标签的全部消息时,接收过程才会退出对MPI_Recv的调用。
发送过程的行为更加复杂(参见后面讲解)。
MPI_STATUS_IGNORE是一个可以用来代替状态变量的预定义常量。
可以创建和传达更复杂的数据结构。