You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于C语言的MPI非阻塞收发与Waitall实现伙伴任务通信需求及问题

基于C语言的MPI非阻塞伙伴通信程序实现

我来帮你补全并完善这个MPI非阻塞通信的程序,先明确你的核心需求:

  • 用C语言编写MPI程序
  • 使用**非阻塞发送(MPI_Isend)和非阻塞接收(MPI_Irecv)**完成进程间通信
  • 伙伴进程规则:对于rank为taskid的进程,伙伴是taskid + numtasks/2;后半段进程的伙伴则是taskid - numtasks/2(避免超出进程总数)
  • 发送的消息内容为发送方自身的rank值

接下来是完整的可运行代码,我会在关键部分加上注释说明:

#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#define MASTER 0

int main (int argc, char *argv[]) {
    int numtasks, taskid, partner, message;
    char hostname[MPI_MAX_PROCESSOR_NAME];
    int len; // 补充你之前省略的变量
    MPI_Request send_req, recv_req; // 非阻塞操作的请求句柄,用于跟踪操作状态
    MPI_Status send_status, recv_status; // 存储非阻塞操作完成后的状态信息

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &numtasks); // 获取总进程数
    MPI_Comm_rank(MPI_COMM_WORLD, &taskid); // 获取当前进程rank
    MPI_Get_processor_name(hostname, &len); // 获取运行进程的主机名

    // 关键检查:总进程数必须是偶数,否则伙伴规则无法覆盖所有进程
    if (numtasks % 2 != 0) {
        if (taskid == MASTER) {
            printf("Error: 进程总数必须为偶数!当前进程数:%d\n", numtasks);
        }
        MPI_Finalize();
        exit(EXIT_FAILURE);
    }

    // 计算伙伴进程的rank
    partner = taskid + numtasks / 2;
    // 处理后半段进程的伙伴(例如总进程数为4时,rank2的伙伴应该是0,而不是4)
    if (partner >= numtasks) {
        partner -= numtasks;
    }

    printf("进程 %d (运行在主机 %s) 的伙伴是进程 %d\n", taskid, hostname, partner);

    // 非阻塞发送:将自身rank发送给伙伴进程
    MPI_Isend(&taskid, 1, MPI_INT, partner, 0, MPI_COMM_WORLD, &send_req);
    // 非阻塞接收:从伙伴进程接收消息到message变量
    MPI_Irecv(&message, 1, MPI_INT, partner, 0, MPI_COMM_WORLD, &recv_req);

    // 等待非阻塞发送和接收操作完成,确保数据安全传输
    MPI_Wait(&send_req, &send_status);
    MPI_Wait(&recv_req, &recv_status);

    // 打印接收结果
    printf("进程 %d 从伙伴进程 %d 接收到消息:%d\n", taskid, partner, message);

    MPI_Finalize();
    return EXIT_SUCCESS;
}

关键代码解释

  • MPI_Request与MPI_Status:非阻塞MPI调用不会等待操作完成,所以需要用MPI_Request来跟踪每个非阻塞操作的状态;MPI_Status则用于获取操作完成后的详细信息(比如实际接收的数据量)。
  • 伙伴计算逻辑:前半段进程的伙伴是自身rank加上总进程数的一半,后半段进程的伙伴则需要减去总进程数,避免rank超出有效范围。
  • 非阻塞调用与等待:MPI_Isend和MPI_Irecv会立即返回,之后必须用MPI_Wait等待操作完成,否则可能出现数据未传输完成就继续执行后续代码的问题。
  • 错误处理:加入了总进程数是否为偶数的检查,确保所有进程都能找到对应的伙伴,避免程序异常。

编译与运行

  • 编译命令:mpicc -o non_blocking_partner non_blocking_partner.c
  • 运行命令(以4个进程为例):mpirun -np 4 ./non_blocking_partner

运行后你会看到每个进程都能正确找到伙伴,并成功发送和接收消息。

内容的提问来源于stack exchange,提问作者SteamedCow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:28:48