MPI笔记

本文详细介绍了MPI中的点对点通信,包括常用函数、MPI_Status结构体的使用,以及点对点通信中的随机游走问题。接着讨论了集体通信,如广播、Scatter、Gather和Allgather,并给出了并行排名问题的解决方法。
摘要由CSDN通过智能技术生成

1 常用函数

MPI_Comm_size(MPI_COMM_WORLD, &world_size);
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
MPI_Barrier(MPI_COMM_WORLD);
MPI_Abort(MPI_Comm comm, int errorcode);

MPI_Send(
    void* data,
    int count,
    MPI_Datatype datatype,
    int destination,
    int tag,
    MPI_Comm communicator);
MPI_Recv(
    void* data,
    int count,
    MPI_Datatype datatype,
    int source,
    int tag,
    MPI_Comm communicator,
    MPI_Status* status);
MPI_Get_count(
    MPI_Status* status,
    MPI_Datatype datatype,
    int* count);
MPI_Probe(
    int source,
    int tag,
    MPI_Comm comm,
    MPI_Status* status);

2 MPI_Status 结构体

MPI_RecvMPI_Status 结构体的地址作为参数(可使用 MPI_STATUS_IGNORE 忽略)。 如果将 MPI_Status 结构体传递给 MPI_Recv 函数,则操作完成后将在该结构体中填充有关接收操作的其他信息。

三个主要的信息包括:

  1. 发送端秩: 发送端的秩存储在结构体的 MPI_SOURCE 元素中。也就是说,声明一个 MPI_Status stat 变量,则可以通过 stat.MPI_SOURCE 访问秩。
  2. 消息的标签: 消息的标签可以通过结构体的 MPI_TAG 元素访问(类似于 MPI_SOURCE)。
  3. 消息的长度:消息的长度在结构体中没有预定义的元素。必须使用 MPI_Get_count 找出消息的长度。
MPI_Get_count(
    MPI_Status* status,
    MPI_Datatype datatype,
    int* count)

MPI_Get_count 函数中,使用者需要传递 MPI_Status 结构体,消息的 datatype(数据类型),并返回 count。 变量 count 是已接收的 datatype 元素的数目。

2.1 MPI_Status 结构体查询的示例

程序将随机数量的数字发送给接收端,然后接收端找出发送了多少个数字。

MPI_Status status;
const int MAX_NUMBERS = 100;
int numbers[MAX_NUMBERS];
int number_amount;
if (world_rank == 0) {
   
    srand(time(NULL));
    number_amount = (rand() / (float)RAND_MAX) * MAX_NUMBERS;
    MPI_Send(numbers, number_amount, MPI_INT, 1, 0, MPI_COMM_WORLD);
    printf("0 sent %d numbers to 1\n", number_amount);
} else if (world_rank == 1) {
   
    MPI_Status status;
    MPI_Recv(numbers, MAX_NUMBERS, MPI_INT, 0, 0, MPI_COMM_WORLD,&status);
    MPI_Get_count(&status, MPI_INT, &number_amount);
    printf("1 received %d numbers from 0. Message source = %d, "
           "tag = %d\n",
           number_amount, status.MPI_SOURCE, status.MPI_TAG);
}

2.2 MPI_Probe 探测接收消息的内容

MPI_Probe(int source,int tag,MPI_Comm comm,MPI_Status* status),在接受之前探测消息,从而决定如何接收。

可将 MPI_Probe 视为 MPI_Recv,除了不接收消息外,它们执行相同的功能。 与 MPI_Recv 类似,MPI_Probe 将阻塞具有匹配标签发送端的消息。 当消息可用时,它将填充 status 结构体。 然后,可以使用 MPI_Recv 接收实际的消息。

else if (world_rank == 1) {
   
    MPI_Status status;
	MPI_Probe(0, 0, MPI_COMM_WORLD, &status);
    MPI_Get_count(&status, MPI_INT, &number_amount);
	int *number_buf = (int *)malloc(sizeof(int) * number_amount);
	MPI_Recv(number_buf, number_amount, MPI_INT, 0, 0,
                 MPI_COMM_WORLD, MPI_STATUS_IGNORE);
	printf("1 dynamically received %d numbers from 0.\n",
               number_amount);
	free(number_buf);
}

3 点对点通信 - 随机游走

引自Point-to-Point Communication Application - Random Walk

随机游走的基本问题定义如下: 给定 MinMax 和随机游走器 W,让游走器 W 向右以任意长度的 S 随机移动。 如果该过程越过边界,它就会绕回。 W 一次只能左右移动一个单位。

随机游走图

尽管程序本身是非常基础的,但是并行化的随机游走可以模拟各种并行程序的行为。 具体内容以后再说。 现在,让我们概述一下如何并行化随机游走问题。

3.1 随机游走问题的并行化

在许多并行程序的应用中,首要任务是在各个进程之间划分域。 随机行走问题的一维域大小为 Max - Min + 1(因为游走器包含 MaxMin)。 假设游走器只能采取整数大小的步长,我们可以轻松地将域在每个进程中划分为大小近乎相等的块。 例如,如果 Min 为 0,Max 为 20,并且我们有四个进程,则将像这样拆分域。

Domain decomposition example

前三个进程拥有域的五个单元,而最后一个进程则拥有最后五个单元并且再加上一个剩余的单元。 一旦对域进行了分区,应用程序将初始化游走器。 如前所述,游走器将以步长 S 进行总步数随机的游走。 例如,如果游走器在进程 0(使用先前的分解域)上进行了移动总数为 6 的游走,则游走器的执行将如下所示:

  1. 游走器的步行长度开始增加。但是,当它的值达到 4 时,它已到达进程 0 的边界。因此,进程 0 必须与进程 1 交流游走器的信息。
  2. 进程 1 接收游走器,并继续移动,直到达到移动总数 6。然后,游走器可以继续进行新的随机移动。

Random walk, step one

在此示例中,W 仅需从进程 0 到进程 1 进行一次通信。 但是,如果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值