MPI多进程场景下如何实现推测性接收多发送进程请求?
MPI稀疏全对全通信的实现方案(解决接收终止判断问题)
问题场景
假设有4个MPI进程(P0、P1、P2、P3),发送关系如下:
- P0 → [P1, P2]
- P1 → [P3]
- P2 → []
- P3 → [P1]
对应接收需求:
- P1需接收来自P0、P3的2个数据包
- P3需接收来自P1的1个数据包
- P2需接收来自P0的1个数据包
- P0无接收需求
核心解决思路
这类稀疏通信的关键是让每个进程预先明确自己需要接收的数据包总数,以此作为循环终止条件,结合MPI_Probe/MPI_MProbe完成接收,避免提前退出循环。
具体实现步骤
1. 确定接收次数
如果通信拓扑是固定的(比如本例),可以直接在代码中硬编码每个进程的接收次数;如果拓扑动态可变,可通过额外通信(如MPI_Allgather)统计:
- 每个进程上报自己的发送目标列表
- 所有进程汇总后,统计自己被多少个进程列为发送目标,得到接收次数
2. 循环接收直到完成计数
每个进程根据自身的接收次数,循环执行探测+接收操作,直到完成所有接收任务。
代码示例(C语言)
#include <mpi.h> #include <stdio.h> int main(int argc, char** argv) { MPI_Init(&argc, &argv); int rank, size; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); // 硬编码接收次数(基于固定拓扑) int recv_count = 0; switch(rank) { case 0: recv_count = 0; break; case 1: recv_count = 2; break; case 2: recv_count = 1; break; case 3: recv_count = 1; break; } // 发送阶段:按拓扑发送数据 int data = rank; if(rank == 0) { MPI_Send(&data, 1, MPI_INT, 1, 0, MPI_COMM_WORLD); MPI_Send(&data, 1, MPI_INT, 2, 0, MPI_COMM_WORLD); } else if(rank == 1) { MPI_Send(&data, 1, MPI_INT, 3, 0, MPI_COMM_WORLD); } else if(rank == 3) { MPI_Send(&data, 1, MPI_INT, 1, 0, MPI_COMM_WORLD); } // 接收阶段:循环指定次数 for(int i = 0; i < recv_count; i++) { MPI_Status status; // 探测任意来源的消息 MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); int src = status.MPI_SOURCE; int recv_data; MPI_Recv(&recv_data, 1, MPI_INT, src, MPI_ANY_TAG, MPI_COMM_WORLD, &status); printf("进程P%d 收到来自P%d的数据:%d\n", rank, src, recv_data); } MPI_Finalize(); return 0; }
补充说明
- 若需处理可变长度消息,推荐用
MPI_MProbe+MPI_Mrecv:通过status获取消息长度后动态分配内存,避免内存浪费或溢出。 - 动态拓扑场景下,可通过
MPI_Allgather收集所有进程的发送目标数组,每个进程遍历数组统计自身被引用的次数,得到接收计数。
内容的提问来源于stack exchange,提问作者foobar
相关产品推荐
相关产品推荐

