使用MPI_Bcast进行MPI通信

86

我正在尝试使用MPI_Bcast将来自根节点的消息广播到所有其他节点。然而,每当我运行此程序时,它总是在开始处挂起。有人知道出了什么问题吗?

#include <mpi.h>
#include <stdio.h>

int main(int argc, char** argv) {
        int rank;
        int buf;
        MPI_Status status;
        MPI_Init(&argc, &argv);
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);

        if(rank == 0) {
                buf = 777;
                MPI_Bcast(&buf, 1, MPI_INT, 0, MPI_COMM_WORLD);
        }
        else {
                MPI_Recv(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
                printf("rank %d receiving received %d\n", rank, buf);
        }

        MPI_Finalize();
        return 0;
}
2个回答

164
这是MPI新手经常困惑的问题。你不使用MPI_Recv()来接收广播发送的数据; 你需要使用MPI_Bcast()。例如,你需要这样做:
#include <mpi.h>
#include <stdio.h>

int main(int argc, char** argv) {
        int rank;
        int buf;
        const int root=0;

        MPI_Init(&argc, &argv);
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);

        if(rank == root) {
           buf = 777;
        }

        printf("[%d]: Before Bcast, buf is %d\n", rank, buf);

        /* everyone calls bcast, data is taken from root and ends up in everyone's buf */
        MPI_Bcast(&buf, 1, MPI_INT, root, MPI_COMM_WORLD);

        printf("[%d]: After Bcast, buf is %d\n", rank, buf);

        MPI_Finalize();
        return 0;
}

对于MPI的集体通信,每个人都必须参与;每个人都必须调用Bcast、Allreduce或者其他类似的函数。(这就是为什么Bcast例程有一个指定“根”的参数,即谁在发送数据;如果只有发送方调用bcast,就不需要这个参数了。) 包括接收方在内,每个人都要调用广播操作;接收方不仅仅是提交一个接收请求。

这样做的原因是因为集体操作可能涉及到所有通信进程,所以你只需说明想要发生什么事情(每个人都得到一个进程的数据),而不是如何实现它(例如,根处理器循环遍历所有其他排名并执行发送操作),这样可以优化通信模式(例如,基于树形层次结构的通信只需要log(P)步骤,而不是P个进程的步骤)。


谢谢您这样解释。然而,我仍然不清楚如何使用MPI_Recv使每个节点接收消息。我尝试在if(rank!= 0)块中包装MPI_Recv调用,也尝试了不包装,但我的程序仍然没有打印任何内容。您知道如何在每个节点上接收消息吗? - David
3
MPI_Bcast不像发送操作,而是一种集体操作,每个人都参与其中,发送方和接收方,在调用结束时,接收方拥有与发送方相同的值。如果rank == root(这里是0),则相同的函数调用执行类似于发送的操作,否则执行类似于接收的操作。我已经更新了上面的代码,以便您可以看到每个人最终都得到了相同的结果。 - Jonathan Dursi
6
如果您将MPI_Bcast视为“参与广播事件”,可能会更加有意义。 - Hugh Perkins
1
这个评论简直是救命稻草...我发誓 MPI 的很多东西在设计意图上都不直观或者含糊不清... - Shane Sepac

3

MPI_Bcast是一种集合操作,必须由所有进程调用以完成。

使用MPI_Bcast时无需调用MPI_Recv。这里有一篇可能对你有帮助的帖子,请点击这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接