0

通常当我们调用 MPI_Bcast 时,必须确定根。但现在我有一个不关心谁会广播消息的应用程序。这意味着将广播消息的节点是随机的,但是一旦消息被广播,全局变量必须是一致的。我的理解是,由于 MPI_Bcast 是一个集合函数,所有节点都需要调用它,但顺序可能不同。所以谁先到达MPI_Bcast,谁将消息广播给其他人。我用3个节点运行了以下代码,我认为如果节点1(rank==1)首先到达MPI_Bcast,它会将local_count值(1)发送到其他节点,然后所有节点都用相同的local_count更新global_count,所以我的预期结果之一是(输出顺序无关紧要)
节点 0,全局计数为 1
节点 1,全局计数为 1
节点 2,全局计数为 1

但实际结果总是(输出顺序无所谓):
节点1,全局计数为1
节点0,全局计数为0
节点2,全局计数为2

这个结果与没有 MPI_Bcast 的代码完全相同。那么我对 MPI_Bcast 或我的代码的理解有什么问题吗?谢谢。

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

int main(int argc, char *argv[])
{   

    int rank, size;
    int local_count, global_count;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    global_count = 0;
    local_count = rank;

    MPI_Bcast(&local_count, 1, MPI_INT, rank, MPI_COMM_WORLD);
    global_count += local_count;

    printf("node %d, global count is: %d\n", rank, global_count);
    MPI_Finalize();
}

该代码是一个简化的案例。在我的应用程序中,在 MPI_Bcast 之前有一些计算,我不知道谁会先完成计算。每当一个节点到达 MPI_Bcast 点时,它需要广播自己的计算结果局部变量,所有节点都更新全局变量。所以所有节点都需要广播一条消息,但我们不知道顺序。如何实现这个想法?

4

3 回答 3

2

的正确用法MPI_BCast是所有进程都以相同的根调用该函数。即使你不关心广播者是谁,所有的进程都必须调用具有相同等级的函数来收听广播者。在您的代码中,每个进程都MPI_BCast以自己的等级调用并且彼此不同。

我还没有查看标准文档,但是您很可能通过MPI_BCast使用不同等级的调用来触发未定义的行为。

于 2012-07-06T04:38:10.023 回答
2

通常你写的东西会导致死锁。在典型MPI_Bcast情况下,具有等级的进程root将其数据发送到通信器中的所有其他进程。您需要root在这些接收进程中指定相同的等级,以便他们知道“听”谁。这是一个过于简单的描述,因为通常使用分层广播来减少总操作时间,但是通过三个进程,这种分层实现减少到非常简单的线性实现。在您的情况下,具有 rank 的进程0将尝试向两个进程发送相同的消息,1并且2. 同时,进程1不会收到该消息,而是会尝试将其发送给进程02。过程2还将尝试发送到0and 1。最后,每个进程都将发送没有其他进程愿意接收的消息。这是一个几乎可以肯定的灾难秘诀。

为什么你的程序没有挂起?因为正在发送的消息非常小,只有一个MPI_INT元素,而且进程的数量也很少,因此这些发送都在每个进程中由 MPI 库在内部进行缓冲——它们永远不会到达目的地,但内部进行的调用MPI_Bcast却没有块,尽管操作仍在进行中,但您的代码会重新获得执行控制权。这是未定义的行为,因为标准不要求 MPI 库缓冲任何内容 - 某些实现可能会缓冲,而其他实现可能不会。

如果您试图计算local_count所有进程中所有变量的总和,那么只需使用MPI_Allreduce. 替换这个:

global_count = 0;
local_count = rank;

MPI_Bcast(&local_count, 1, MPI_INT, rank, MPI_COMM_WORLD);
global_count += local_count;

有了这个:

local_count = rank;
MPI_Allreduce(&local_count, &global_count, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
于 2012-07-06T14:30:33.070 回答
0

来自 openmpi 文档

"MPI_Bcast broadcasts a message from the process with rank root to all processes of the group, itself included. It is called by all members of group using the same arguments for comm, root. On return, the contents of root’s communication buffer has been copied to all processes. "

调用它可能会从等级!= root 可能会导致一些问题

一种更安全的方法是硬编码你自己的广播函数并调用它

它基本上是一个 for 循环和一个 mpi_send 命令,应该不难实现你自己

于 2012-07-06T05:04:19.873 回答