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是用来存放接收消息的消息状态,包括:

  1. 消息的原进程标识——MPI_SOURCE
  2. 消息标签——MPI_TAG
  3. 错误状态——MPI_ERROR
  4. 其他——包括数据项个数等。

假设多个客户进程发送消息给服务进程请求服务,通过消息标签来标识客户进程,从而服务进程采取不同的服务,示例如下:

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同时有阻塞非阻塞两种通信机制,它们的主要区别是返回后资源的可用性。阻塞通信的返回条件如下:

  1. 通信操作已经完成,即消息已发送或接收
  2. 调用的缓冲区可用性,若是发送操作,则该缓冲区可以被其他操作更新;若是接收操作,该缓冲区的数据已经完整,可以被正确引用。

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 路障同步
posted @   ZhenweiCao  阅读(1516)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示