当 MPI_Send 不阻塞时

When MPI_Send doesn't block

我使用了一些实现手动 MPI 广播的代码,基本上是一个将整数从根节点单播到所有其他节点的演示。当然,单播到多个节点的效率不如 MPI_Bcast() 但我只是想检查一下它是如何工作的。

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

void my_bcast(void* data, int count, MPI::Datatype datatype, int root, MPI::Intracomm communicator) {
    int world_size = communicator.Get_size();
    int world_rank = communicator.Get_rank();

    if (world_rank == root) {
        // If we are the root process, send our data to everyone
        int i;
        for (i = 0; i < world_size; i++) {
            if (i != world_rank) {
                communicator.Send(data, count, datatype, i, 0);
            }
        }
    } else {
        // If we are a receiver process, receive the data from the root
        communicator.Recv(data, count, datatype, root, 0);
    }
}

int main(int argc, char** argv) {
    MPI::Init();

    int world_rank = MPI::COMM_WORLD.Get_rank();

    int data;
    if (world_rank == 0) {
        data = 100;
        printf("Process 0 broadcasting data %d\n", data);
        my_bcast(&data, 1, MPI::INT, 0, MPI::COMM_WORLD);
    } else {
        my_bcast(&data, 1, MPI::INT, 0, MPI::COMM_WORLD);
        printf("Process %d received data %d from root process\n", world_rank, data);
    }

    MPI::Finalize();
}

我注意到,如果我删除根不发送给自己的支票,

if (i != world_rank) {
...
}

该程序仍然有效并且不会阻塞,而 MPI_Send() 的默认行为应该是阻塞的,即等待另一端接收到数据。但是 MPI_Recv() 永远不会被根调用。有人可以解释为什么会这样吗?

我 运行 使用以下命令从 root 获取代码(集群在 Amazon EC2 上设置并使用 NFS 作为节点之间的共享存储,所有机器都安装了 Open MPI 1.10.2)

mpirun -mca btl ^openib -mca plm_rsh_no_tree_spawn 1 /EC2_NFS/my_bcast

C文件用

编译

mpic++ my_bcast.c

mpic++版本是5.4.0。

代码取自www.mpitutorial.com

您将 阻塞 误认为是 同步 行为。阻塞意味着调用不会 return 直到操作完成。一旦提供的缓冲区可以被程序重新使用,标准发送操作 (MPI_Send) 就会完成。这意味着消息要么完全传输到接收方,要么由 MPI 库内部存储以供以后传送(缓冲发送)。缓冲行为是特定于实现的,但大多数库将缓冲单个整数大小的消息。通过使用 MPI_Ssend(或 C++ 等效项)强制同步模式让您的程序挂起。

请注意,C++ MPI 绑定不再是标准的一部分,不应在新软件开发中使用。请改用 C 绑定 MPI_Blabla