MPI通信相关函数

发布时间 2023-04-07 11:21:43作者: Laplace蒜子

MPI环境操作

初始化

MPI_INIT

结束

MPI_FIANLIZE

 

MPI通信子操作

MPI_COMM_SIZE

MPI数据类型

通信函数

SEND()函数

格式

int MPI_Send( void* buf, int count, MPI_Datatype datatype,int dest, int tag, MPI_Comm comm )

        • buf:发送数据buffer
        • count:发送数据长度
        • datatype:MPI数据类型
        • dest:发送的目的进程号
        • tag:发送数据的标记
        • comm:通信域

MPI_Isend()

Send的异步形式,多了个MPI_Request参数,用于异步返回消息的状态。

异步通信并不意味着异步发送消息后执行到MPI_Finailize()自动结束,而是在结尾等待这个异步的消息被接收,否则程序不会结束。

MPI_Recv()函数

格式

int MPI_Recv( void* buf, int count, MPI_Datatype datatype,int source, int tag, MPI_Comm comm, MPI_Status *status )

参数说明

        • buf:发送数据buffer
        • count:接收数据长度
        • datatype:MPI数据类型
        • source:接收数据的进程号
        • tag:接收数据的标记
        • comm:通信域
        • status:通信状态

缺点

阻塞式通信,可能会导致死锁。

MPI_Irecv()函数

MPI_Recv()的异步形式,多了个MPI_Request参数,用于异步返回消息的状态。

 

Sendrecv()函数

格式

int MPI_Sendrecv( void *sendbuf, int sendcount,MPI_Datatype sendtype, int dest, int sendtag,void *recvbuf, int recvcount, MPI_Datatype recvtype,int source,int recvtag,MPI_Comm comm,MPI_Status *status)

参数说明:

        • sendbuf:发送数据的buffer
        • sendcount:发送数据的长度,通常采用 sizeof() 计算
        • sendtype:发送数据的类型
        • dest:发送的目的地址
        • sendtag:发送数据的标签
        • recvbuf:接收数据的buffer
        • recvcount:接收数据的长度
        • recvtype:接收数据的类型
        • source:接收数据的地址
        • recvtag:接收数据的tag
        • comm:通讯域
        • status:状态

优点

不用管先发送还是先接收的问题,避免了死锁。

SENDRECV_REPLACE函数

格式

int MPI_Sendrecv_replace( void *buf, int count,MPI_Datatype type, int dest, int sendtag,int source,int recvtag,MPI_Comm comm,MPI_Status *status)

参数与Sendrecv基本一致,

缺少了接收数据的buffer,长度,类型。

作用

发送完用接收到的替换原本buffer。

缺点

只允许buffer一致。

效率低下,时间开销大,需要复制数据到buffer。

通配符

任意进程

source=MPI_ANY_SOURCE:接收来源于任意进程的消息

tag=MPI_ANY_TAG:接收任意tag的消息

空进程

MPI_PROC_NULL表示,并不是真正的接收或发送进程,解决边界进程阻塞通信的问题。

案例

0号进程接收所有进程的消息。


#include <iostream>
#include"mpi.h"
#include"string.h"
#define MESSAGESIZE 50
int main(int argc,char *argv[])
{
    MPI_Init(&argc,&argv);
    int id;
    int pronumber;
    MPI_Comm_rank(MPI_COMM_WORLD,&id);
    MPI_Comm_size(MPI_COMM_WORLD, &pronumber);

    if (id == 0) {
        char string[MESSAGESIZE];
        for (int i = 1;i < pronumber;i++) {
            MPI_Status status;
            MPI_Recv(string, MESSAGESIZE, MPI_CHAR, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
            printf("%s\n", string);
        }
    }
    else {
        char string[] = "Bullshit! It is nonsense!";
        char thisid[MESSAGESIZE] = "From id:0:";
        thisid[8] = '0' + id;
        strcat_s(thisid, string);
        MPI_Request request;
        MPI_Isend(thisid, sizeof(thisid), MPI_CHAR, 0, id, MPI_COMM_WORLD, &request);
    }
    MPI_Finalize();
}

 

消息查询函数

MPI_PROBE

作用:探测source地址,标记为tag的消息。直到source地址发送了标记为tag的消息,否则一致阻塞在这一步。

格式:int MPI_Probe(int source, int tag, MPI_Comm comm,MPI_Status *status )

MPI_IPROBE

int MPI_Iprobe(int source, int tag, MPI_Comm comm,int* flag, MPI_Status *status )

Probe的异步形式

MPI_GET_COUNT

作用:获取消息的大小,从前文接收到消息后的status中获取,通常与Probe一起使用。

格式:int MPI_Get_count( MPI_Status *status, MPI_Datatype type,int *count )

消息请求完成函数

MPI_Wait()函数

作用:等待上一个未完成的操作完成。

格式:int MPI_Wait( MPI_Request *request, MPI_Status *status )

MPI_WaitAny()函数

作用:等待未完成的多个操作中,其中一个完成即可继续。

格式:int MPI_Waitany( int count, MPI_Request *requests,int *index, MPI_Status *status )

      • count:多个未完成操作的句柄MPI_Request集合的大小
      • requests:多个未完成操作的句柄MPI_Request集合
      • index:指向其中一个完成操作的下标,返回。

MPI_Waitall()函数

作用:等待所有未完成的操作完成。

格式:int MPI_Waitaall( int count, MPI_Request *requests, MPI_Status *status )

      • count:多个未完成操作的句柄MPI_Request集合的大小
      • requests:多个未完成操作的句柄MPI_Request集合
      • statuses:所有未完成操作的status集合

MPI_WaitSome()函数

作用:等待未完成的多个操作中,完成指定个数即可继续。

格式:int MPI_Waitany( int incount, MPI_Request *requests,int *outcount,int *indices, MPI_Status *statuses)

      • incount:多个未完成操作的句柄MPI_Request集合的大小
      • requests:多个未完成操作的句柄MPI_Request集合
      • outcount:等待完成操作的个数
      • indeices:已完成操作的索引数组
      • statuses:所有未完成操作的status集合

消息请求检查函数

MPI_Test()函数

作用:测试指定request是否完成,结果保存在flag中,非0表示完成。

格式:int MPI_Test( MPI_Request *request, int *flag, MPI_Status *status )

MPI_Testany()函数

作用:测试指定requests集合中是否有其中的一个完成,完成结果保存在flag中,非0表示完成,完成的request下标保存在index中。

格式:int MPI_Test( int count, MPI_Request *requests, int *index, int *flag, MPI_Status *status)

MPI_Testall()函数

作用:测试指定requests集合中所有request是否完成,完成结果保存在flag中,非0表示所有的都完成。

格式:int MPI_Test(int count, MPI_Request *requests, int *flag, MPI_Status *statuses)

MPI_Testsome()函数

作用:测试指定requests集合中指定outcount个数的request是否完成,indices保存已完成的request索引数组

格式:int MPI_Testsome(int incount, MPI_Request *requests,int *outcount,int *indices, MPI_Status *statuses )

MPI_Send_INIT()函数

作用:建立发送消息请求通道,当调用MPI_Start()函数时才开始发送。

格式:int MPI_Send_init(void* buf, int count, MPI_Datatype type,int dest, int tag, MPI_Comm comm, MPI_Request *request)

参数与Send相同。

MPI_Recv_INIT()函数

作用:建立接收消息请求通道,当调用MPI_Start()函数时才开始发送。

格式:MPI__Recv_init(void* buf, int count, MPI_Datatype type,int src, int tag, MPI_Comm comm, MPI_Request *request)

参数与Recv相同。

消息请求的释放与取消

MPI_Start()函数

作用:启动request的消息请求。

格式:int MPI_Start( MPI_Request *request )

MPI_Startall()函数

作用:启动大小为count的requests中所有的消息请求。

格式:int MPI_Start( int count, MPI_Request *requests )

MPI_Cancel()函数

作用:取消request的消息请求。

格式:int MPI_Cancel( MPI_Request *request )

 

MPI_Test_Cancelled()函数

作用:测试请求status的状态,保存在flag中,非0表示请求已经完成。

格式:int MPI_Test_Cancelled( MPI_Status *status, int *flag )

 

释放句柄函数Request_Free()

作用:释放句柄。使用Send_init或Recv_init后,句柄还在系统中,为了避免系统资源枯竭,可是使用此函数释放

格式:int MPI_Request_Free( MPI_Request request )

使用注意:使用Isend或Irecv等产生的句柄,若将其取消了后,函数将失去作用。