MPICH笔记(一):通信子

MPICH笔记:简单使用MPICH(一)

使用MPICH需要导入的头文件:

mpi.h

MPICH函数的命名规则:

MPI_Xxxx_xxx…即以MPI开头第二个单词的首字母大写,后面单词的首字母全部小写,单词之间用_隔开。

MPICH预定义常量命名规则:

MPI_XXXX_XXXX…即以MPI开头,每个字母都大写。

 

示例代码:

#include "mpi.h"
#include <cstdio>
#include <iostream>

using namespace std;

int main(int argc, char **argv) {
    int wrank, wsize, mrank;
    MPI_Init(&argc, &argv);
    /*
    * MPI_COMM_WORLD 和 MPI_COMM_SELF 是两个预定义的通信子(或者叫通信域, communicator),
    * MPI_COMM_WORLD 包含了所有进程,
    * MPI_COMM_SELF 仅包含自身进程。
    */
    MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
    MPI_Comm_size(MPI_COMM_WORLD, &wsize);
    MPI_Comm_rank(MPI_COMM_SELF, &mrank);
    printf("World rank %d, world size %d, self rank %d\n", wrank, wsize, mrank);
    MPI_Finalize();
    return 0;
}

输出:

World rank 2, world size 4, self rank 0
World rank 0, world size 4, self rank 0
World rank 3, world size 4, self rank 0
World rank 1, world size 4, self rank 0

注:输出顺序可能有所不同,因为是由多个进程同时执行,执行先后会有差异。

代码简述:

通信子(通信域,communicator):

MPI的通信子包含一组进程以及一个(隐藏的)通信文本,通信文本的作用在于保证消息和库的一致性\(^{[1]}\)。

MPICH有两个预定义的communicator,分别是MPI_COMM_WORLD和MPI_COMM_SELF,前者包含所有进程,后者只包含自身进程。

MPI_Comm_rank(MPI_Comm, int *)

获得进程在通信子comm中的编号。保存在int *参数所指向的空间中。

MPI_Comm_size(MPI_Comm, int *)

获得通信子comm中进程个数,保存在int *参数所指向的空间中。

MPI_Init(int *, char **)

初始化。

MPI_Finalize()

结束。

注:大多数MPI函数都需要在MPI_Init(int *, char **)之后,且在MPI_Finalize()之前使用。

 

手动创建通信子:

#include "mpi.h"
#include <iostream>

using namespace std;

int main(void) {
    int mrank, wrank, wsize;
    MPI_Comm *evenAndOddComm = new MPI_Comm();
    MPI_Init(nullptr, nullptr);
    MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
    MPI_Comm_size(MPI_COMM_WORLD, &wsize);
    /*
    * create a new commonicator
    */
    if (wrank & 1) MPI_Comm_split(MPI_COMM_WORLD, 1, wrank >> 1, evenAndOddComm);
    else MPI_Comm_split(MPI_COMM_WORLD, 2, wrank >> 1, evenAndOddComm);
    MPI_Comm_rank(*evenAndOddComm, &mrank);
    printf("Message from world rank %d -> world size %d, myColor is %d, and mrank is %d\n",
        wrank, wsize, wrank & 1 ? 1 : 2, mrank);
    MPI_Comm_free(evenAndOddComm);
    delete evenAndOddComm;
    MPI_Finalize();
    return 0;
}

代码简述:

MPI_Comm_split(MPI_Comm, int color, int key, MPI_Comm *out)

得到comm中进程的划分,具有相同color值的通信子会被划分到同一个新的通信子中,out指向的空间存放新的通信子相关的信息,key将是调用该函数的进程在新的通信子中的序号。特别地,color可以指定为MPI_UNDEFINED,但是这样调用函数后得到的out将不可用,如调用MPI_Comm_rank()函数时会产生异常。

MPI_Comm_free(MPI_Comm *)

释放通信子。

 

参考资料:

[1]: 《并行计算的编程模型(Programming Models for Parallel Computing)》第一版,Pavan Balaji [美]、美国阿贡国家实验室编著,张云泉、李士刚、逄仁波、袁良译,机械工业出版社。