MPI学习--消息传递通信
本文主要总结MPI消息传递的一些基本概念
MPI的工作模式
目前我对MPI的工作模式的理解就是他其实呢是把一份程序传送到不同的进程中,通过MPI的接口我们可以获取当前进程中的一些信息,例如进程号,进程总数等,这样我们就可以在程序中显式的对进程信息进行判断,然后做不同的处理,这样同一份程序在不同的进程中做的事情是不一样的,尽管代码(变量,函数等)都是一样的,可见这种并行的粒度是很大的。
下面引用下书里的一段话:
MPI程序工作模式
在不同工作模式下可以适合SPMD或者MPMD等体系结构。以串行方式编写,运行时分别执行不同的块。
这里的不同的块其实就是通过MPI提供的接口获取的进程信息进而写出的条件判断语句。
所有程序元素,只要没进行显式区分,不论是代码,函数,全局变量还是局部变量,都默认的有全部进程所共有,所有进程里看到的虽然是相同的名字,但在“物理”上却彼此无关。同一个变量,在不同的进程空间看来,是物理上互不联系的,属于各个进程的私有变量。当然,从语义角度看,在逻辑上他们则应属于描述同一事物的不同部分,或同为构成事物模型的某种属性/特征等。
上面这段虽然说的很高大上,但是本质还是我最开始理解的那些啦。
MPI消息传递
这里我就总结下MPI的消息部分。
在通信过程中,MPI消息被封装在“信封”中,然后经过MPI环境自己的缓冲区在交由网络传输层打包发送。
基本的MPI消息传递封装大致代码总结可以如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 初始化MPI环境
MPI_Init(&argc, &argv);
// 获取当前进程的进程号
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// 获取当前所有进程个数
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Send(buf, size, datatype, target, tag, MPI_COMM_WORLD);
MPI_Recv(buf, size, datatype, source, tag, MPI_COMM_WORLD, &status);
MPI_Finalize();
通过发送和接收消息的接口参数就可以看出,这些消息可以跟信件的收发一一联系起来。buf
, size
, datatype
:这些是被信封包起来的数据部分。target
:是收件人的信息,即邮编和地址,收件人姓名等。source
:是寄件人的信息,邮编、地址、姓名等。tag
:邮戳,这样就可以区分信件的顺序。MPI_COMM_WORLD
:邮局名称,收发信件通过的邮局。
上面代码中有个status
,他是一个MPI定义的结构,用来保存执行结果(状态):1
2
3
4
5
6
7typedef struct MPI_Status {
int cout; // 记录发送/接收的字节数
int cancelled;
int MPI_SOURCE; // 记录接收消息的源进程
int MPI_TAG; // 记录消息的标志值
int MPI_ERROR;
};
当我们使用MPI_ANY_SOURCE
和MPI_ANY_TAG
的时候可以通过这个结构来判断接收到的数据来源。
点到点通信
点到点通信要求必须有send
和recv
配对。消息通信的数据传递流程如下:
- 发送端发起数据发送调用
MPI_??Send
- MPI环境从发送缓冲区提取要发送的数据,据此组装发送消息。
- 将组装的消息发动个目标进程。
- 接收端收取可匹配的消息,并将其解析到自己的接收缓冲区中。