MPI基础内容介绍
MPI 基础内容
1. MPI基本函数
1.1 初始化
int MPI_Init(int *argc, char ** argv)
通过MPI_Init
进入MPI环境,并完成初始化工作。
1.2 结束
int MPI_Finalize(void)
从MPI环境中退出
1.3 获取进程编号
int MPI_Comm_rank(MPI_Comm comm, int *rank)
获取当前进程在指定通信域中的编号,其中MPI_Comm
代表一个通信域。一个通信域指的是一个进程组和对应的通信上下文,常用的常量MPI_COMM_World
是所有进程在的通信域。编号保存在变量rank中。
1.4 获取进程数目
int MPI_Comm_size(MPI_Comm comm, int *size)
获得当前通信域中的进程数目,数目保存在变量size中。
1.5 发送消息
int MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)
参数buf指的是要发送内容的首地址,count指的是发送的元素数目。datatype指的是要发送的数据类型,C语言中的数据类型,会与MPI的数据类型绑定,比如int会在MPI中绑定为MPI_INT。MPI预定义的数据类型表如下(部分内容):
MPI(C语言绑定) | C语言中的数据类型 |
---|---|
MPI_BYTE | |
MPI_DOUBLE | double |
MPI_FLOAT | float |
MPI_INT | int |
MPI_UNSIGNED_CHAR | unsigned char |
MPI_CHAR | signed char |
消息信封指的是<源/目的地址(source/dest),消息标签(tag),通信域(MPI_Comm)>,表示接收/发送消息的地址。其中source/dest指的是源/目的进程的进程号,即从函数MPI_Comm_rank
中获得的rank值。
1.6 接收消息
int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)
变量status指的是返回状态。在C语言中,状态变量至少是由三部分组成的数据结构类型,这三个部分分别是MPI_SOURCE,MPI_TAG和MPI_ERROR,还可以包含其他部分。传递MPI_Status
参数时,需用语句MPI_Status status;
生成一个MPI_Status
类型的变量,然后将地址传入。
1.7 简单示例
一个简单的MPI示例如下
#include "mpi.h" /*MPI头函数,提供了MPI函数和数据类型定义*/
int main( int argc, char** argv )
{
int rank, size, tag=1;
int senddata,recvdata;
MPI_Status status;
MPI_Init(&argc, &argv); /*MPI的初始化函数*/
MPI_Comm_rank(MPI_COMM_WORLD, &rank); /*该进程编号*/
MPI_Comm_size(MPI_COMM_WORLD, &size); /*总进程数目*/
if (rank==0){
senddata=9999;
MPI_Send( &senddata, 1, MPI_INT, 1, tag, MPI_COMM_WORLD); /*发送数据到进程1*/
}
if (rank==1)
MPI_Recv(&recvdata, 1, MPI_INT, 0, tag, MPI_COMM_WORLD, &status); /*从进程0接收数据*/
MPI_Finalize(); /*MPI的结束函数*/
return (0);
}
2. 通信方式
2.1 通信域
通信域(Communicator)包括进程组(Process Group)和通信上下文等内容,用于描述通信进程之间的关系。进程组是进程的有限有序集合,集合的数目称为进程组的大小,在一个大小为n的进程组中,进程按照0,1,2,……,n-1进行排列。通信上下文不是显示的对象,只是作为通信域的一部分出现,用于安全的区别不同的通信以免互相干扰。MPI_COMM_WORLD是所有进程的集合。
通信域分为组内通信域和组间通信域,分别用来实现MPI的组内通信(Intra-communication)和组间通信(Inter-communication)。
2.2 管理通信域
常见的用于管理通信域的函数如下
函数名 | 含义 |
---|---|
MPI_Comm_size | 获取指定通信域中进程的个数 |
MPI_Comm_rank | 获取当前进程在指定通信域中的编号 |
MPI_Comm_compare | 对给定的两个通信域进行比较 |
MPI_Comm_dup | 复制一个已有的通信域生成一个新的通信域,两者除通信上下文不同外,其它都一样。 |
MPI_Comm_create | 根据给定的进程组创建一个新的通信域 |
MPI_Comm_split | 从一个指定通信域分裂出多个子通信域,每个子通信域中的进程都是原通信域中的进程。 |
MPI_Comm_free | 释放一个通信域 |
一个在MPI中创建新通信域的例子
MPI_Comm MyWorld, SplitWorld;
int my_rank,group_size, Color, Key;
MPI_Init(&argc, &argv);
MPI_Comm_dup(MPI_COMM_WORLD,&MyWorld);
MPI_Comm_rank(MyWorld,&my_rank);
MPI_Comm_size(MyWorld,&group_size);
Color=my_rank%3;
Key=my_rank/3;
MPI_Comm_split(MyWorld,Color,Key,&SplitWorld);
解释如下
-
MPI_Comm_dup
MPI_Comm_dup(MPI_COMM_WORLD, &MyWorld)
创建一个新通信域MyWorld,包含于原通信域MPI_COMM_WORLD中相同的进程,但是具有不同的上下文。
-
MPI_Comm_split
MPI_Comm_split(MyWorld, Color, Key, &SplitWorld)
在通信域MyWorld的基础上,产生几个分割的通信域。原通信域中MyWorld中的进程按照不同的Color值处在不同的通信域中,每个进程在不同分割通信域中的编号则有Key值标识。
Rank in MyWorld 0 1 2 3 4 5 6 7 8 9 Color 0 1 2 0 1 2 0 1 2 0 Key 0 0 0 1 1 1 2 2 2 3 Rank in SplitWorld(Color=0) 0 1 2 3 Rank in SplitWorld(Color=1) 0 1 2 Rank in SplitWorld(Color=2) 0 1 2
2.3 组间通信
组间通信域是一种特殊的通信域,该通信域包括两个进程组。不同进程组的进程通过组间通信域进行通信。一般把调用进程所在的进程组称为本地进程组,而把另外一个称为远程进程组。
函数名 | 含义 |
---|---|
MPI_Comm_test_inter | 判断给定的通信域是否为组间通信域 |
MPI_Comm_remote_size | 获取指定组间通信域中远程进程组的大小 |
MPI_Comm_remote_group | 返回给定组间通信域的远程进程组 |
MPI_Intercomm_creat | 根据给定的两个组内通信域生成一个组间通信域。 |
MPI_Intercomm_merge | 将给定组间通信域包含的两个进程组合并,形成一个新的组内通信域 |
2.4 消息状态
MPI_Status
是用来存放接收消息的消息状态,包括:
- 消息的原进程标识——MPI_SOURCE
- 消息标签——MPI_TAG
- 错误状态——MPI_ERROR
- 其他——包括数据项个数等。
假设多个客户进程发送消息给服务进程请求服务,通过消息标签来标识客户进程,从而服务进程采取不同的服务,示例如下:
while (true){
MPI_Recv(received_request,100,MPI_BYTE,MPI_Any_source,MPI_Any_tag,comm,&Status);
switch (Status.MPI_Tag) {
case tag_0: perform service type0;
case tag_1: perform service type1;
case tag_2: perform service type2;
}
2.5 点对点通信模式
MPI支持四种通信模式,同步、缓冲、标准、就绪四种。
-
同步通信模式
只有等相应等接收过程已经启动,发送过程才能正确返回。
因此,当同步发送返回时,表示发送缓冲区中的数据已经被系统缓冲区缓存,并且已经开始发送。
-
缓冲通信模式
缓冲通信模式的发送不管接收操作是否已经启动都可以执行。
但是需要用户程序事先申请一块足够大的缓冲区,通过MPI_Buffer_attch实现,通过MPI_Buffer_detach来回收申请的缓冲区。
-
标准通信模式
是否对发送的数据进行缓冲由MPI的实现来决定,而不是由用户程序来控制。发送是可以同步或缓冲的,取决于具体实现。
-
就绪通信模式
发送操作只有在接收进程相应的接收操作已经开始才进行发送。
当发送操作启动而相应的接收还没有启动,发送操作将出错。就绪通信模式的特殊之处是接收操作必须先于发送操作启动。
MPI同时有阻塞和非阻塞两种通信机制,它们的主要区别是返回后资源的可用性。阻塞通信的返回条件如下:
- 通信操作已经完成,即消息已发送或接收
- 调用的缓冲区可用性,若是发送操作,则该缓冲区可以被其他操作更新;若是接收操作,该缓冲区的数据已经完整,可以被正确引用。
MPI的发送支持四种通信模式,与阻塞属性一起产生了MPI的8种发送操作,但是对于接收,只有阻塞接收和非阻塞接收两种。
2.6 群集通信
群集通信是一个进程组中的所有进程都参加的全局通信操作,一般实现三个功能:通信、聚集和同步。通信主要完成组内数据的传输,聚集功能在通信的基础上对给定的数据完成一定的操作,同步功能实现组内所有进程在执行进度上的一致性。
群集通信按照通信方向的不同,可以分为一对多通信、多对一通信和多对多通信,常见的通信函数如下:
类型 | 函数名 | 含义 |
---|---|---|
通信 | MPI_Bcast | 一对多广播同样的消息 |
MPI_Gather | 多对一收集各个进程的消息 | |
MPI_Gatherv | MPI_Gather的一般化 | |
MPI_Allgather | 全局收集 | |
MPI_Allgatherv | MPI_Allgather的一般化 | |
MPI_Scatter | 一对多散播不同的消息 | |
MPI_Scatterv | MPI_Scatter的一般化 | |
MPI_Alltoall | 多对多全局交换消息 | |
MPI_Alltoallv | MPI_Alltoall的一般化 | |
聚集 | MPI_Reduce | 多对一归约 |
MPI_Allreduce | MPI_Reduce的一般化 | |
MPI_Reduce_scatter | MPI_Reduce的一般化 | |
MPI_Scan | 扫描 | |
同步 | MPI_Barrier | 路障同步 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)