六个接口是最常用的,也是最基本的

1. MPI初始化

1
2
3
MPI_INIT( )
//相当于C中
int MPI_Init(int *argc,char ***argv)

初始化MPI系统,所有MPI程序的第一条可执行语句都是这条。在许多MPI系统中,第一个进程通过MPI_Init来启动其他进程。

2. MPI结束

1
2
3
MPI_FINALIZE( )
//相当于C中
int MPI_Finalize(void)

用于退出MPI系统,是MPI程序的最后一个调用,否则程序的运行结果不可预知。

3. 当前进程标识

1
2
3
4
5
MPI_COMM_RANK(comm,rank)
IN comm 该进程所在的通信域
OUT rank 调用进程在comm中的标识号
//相当于C中
int MPI_Comm_rank(MPI_Comm comm,int *rank)

这一调用返回调用进程在给定的通信域中的进程标识号,有了这一标识号,不同的进程就可以将自身和其他的进程区别开来,实现各进程的并行和协作。

4. 通信域包含的进程数

1
2
3
4
5
MPI_COMM_SIZE(comm,size)
IN comm 该进程所在的通信域(句柄)
OUT size 通信域comm内包括的进程数(整数)
//相当于C中
int MPI_Comm_size(MPI_Comm comm,int *size)

这一调用返回调用给定的通信域中所包含的进程的个数,不同的进程通过这一调用得知在给定的通信域中一共有多少个进程在并行执行。

5. 消息发送

1
2
3
4
5
6
7
8
9
MPI_SEND(buf,count,datatype,dest,tag,comm)
IN buf 发送缓冲区的起始地址(可选类型)
IN count 将发送数据的个数(非负整数)
IN datatype 发送数据的数据类型(句柄)
IN dest 目的进程标识号(整型)
IN tag 消息标志(整型)
IN comm 通信域(句柄)
//相当于C中
int MPI_Send(void *buf , int count , MPI_Datatype datatype , int dest , int tag , MPI_Comm comm)

MPI_SEND将发送缓冲区中的count个datatype数据类型的数据发送到目的进程,目的进程在通信域中的标识号是dest,本次发送的消息标志是tag,使用这一标志,就可以把本次发送的消息和本进程向同一目的进程发送的其它消息区别开来。

MPI_SEND操作指定的发送缓冲区是由count个类型为datatype的连续数据空间组成,起始地址为buf 。注意这⾥不是以字节计数,⽽是以数据类型为单位指定消息的⻓度,这样就独⽴于具体的实现 ,并且更接近于⽤户的观点。

其中datatype数据类型可以是MPI的预定义类型,也可以是⽤户⾃定义的类型,将在后
⾯的部分介绍,通过使⽤不同的数据类型调⽤MPI_SEND,可以发送不同类型的数据。

6. 消息接收

1
2
3
4
5
6
7
8
9
10
MPI_RECV(buf,count,datatype,source,tag,comm,status)
OUT buf 接收缓冲区的起始地址(可选类型)
IN count 最多可接收的数据的个数(整型)
IN datatype 接收数据的数据类型(句柄)
IN source 接收数据的来源即发送数据的进程的进程标识号(整型)
IN tag 消息标识,与相应的发送操作的表示相匹配相同(整型)
IN comm 本进程和发送进程所在的通信域(句柄)
OUT status 返回状态 (状态类型)
//相当于C中
int MPI_Recv(void *buf , int count , MPI_Datatype datatype , int source , int tag , MPI_Comm comm , MPI_Status *status)

MPI_RECV从指定的进程source接收消息,并且该消息的数据类型和消息标识和本接收
进程指定的datatype和tag相⼀致,接收到的消息所包含的数据元素的个数最多不能超过count。

接收缓冲区是由count个类型为datatype的连续元素空间组成,由datatype指定其类型,起始地址为buf。接收到消息的⻓度必须⼩于或等于接收缓冲区的⻓度,这是因为如果接收到的数据过⼤,MPI没有截断,接收缓冲区会发⽣溢出错误,因此编程者要保证接收缓冲区的⻓度不⼩于发送数据的⻓度。如果⼀个短于接收缓冲区的消息到达,那么只有相应于这个消息的那些地址被修改, count可以是零,这种情况下消息的数据部分是空的。

其中datatype数据类型可以是MPI的预定义类型,也可以是⽤户⾃定义的类型。通过指
定不同的数据类型调⽤MPI_RECV,可以接收不同类型的数据。

7. 返回状态status

返回状态变量status⽤途很⼴,它是MPI定义的⼀个数据类型,使⽤之前需要⽤户为它分
配空间。在C中,状态变量是由⾄少三个域组成的结构类型,这三个域分别是:MPI_SOURCE,MPI_TAG和MPI_ERROR。它还可以包括其它的附加域。这样通过对
status.MPI_SOURCE status.MPI_TAG和status.MPI_ERROR的引⽤,就可以得到返回状态中所包含的发送数据进程的标识,发送数据使⽤的tag标识和本接收操作返回的错误代码。

除了以上三个信息之外,对status变量执⾏MPI_GET_COUNT调⽤可以得到接收到的消
息的⻓度信息。

#例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//⼀个简单的发送和接收的例⼦
/*算法说明
其中一个进程(进程0)向另一个进程(进程1)发送一条消息,该消息是一个字符串"Hello,process 1",该进程1在接收到该消息后,将这一消息打印到屏幕上。*/

#include "mpi.h"
#include<stdio.h>
#include<string.h>
int main(argc,argv)
int argc;
char **argv;
{
char message[20];
int myrank;
//定义返回状态变量
MPI_Status status;

//MPI程序的初始化
MPI_Init(&argc,&argv);

//得到进程的标识
MPI_Comm_rank(MPI_COMM_WORLD,&myrank);

if(myrank==0)//若是0进程
{
/*先将字符串拷贝到发送缓冲区message中,然后调用MPI_Send语句将它发出,用strlen(message)指定消息的长度,用MPI_CHAR指定消息的数据类型,1指明发往进程1,使用的消息标识是99,MPI_COMM_WORLD是包含本进程(进程0)和就收消息进程(进程1)的通信域。发送和接收必须在同一个通信域中。由通信域统一协调和控制消息的发送和接收*/
strcpy(message,"Hello,process 1");
MPI_Send(message,strlen(message),MPI_CHAR,1,99,MPI_COMM_WORLD);
}
else if(myrank==1)//若进程是1
{
/*进程1直接执行接收消息的操作,这里它使用message作为接收缓冲区,由此可见,对于同一个变量,在发送进程和接收进程中的作用是不同的。它指定接收消息的最大长度为20,消息的数据类型为MPI_CHAR字符型,接收的消息来自进程0,而接收消息携带的标识必须为99,使用的通信域也是MPI_COMM_WORLD,接收完成后的各种状态信息存放在status中。接收完成后,它直接将接收到的字符串打印在屏幕上。*/
MPI_Recv(message,20,MPI_CHAR,0,99,MPI_COMM_WORLD,&status);
printf("received : %s",message);
}
//MPI程序的结束
MPI_Finalize();
}