一个不安全的MPI非阻塞通信示例?

问题描述 投票:0回答:1

我正在程序内部实现MPI无阻塞通信。我在MPI_Isend man_page上看到,它说:

无阻塞发送调用表示系统可能开始从发送缓冲区中复制数据。在调用无阻塞发送操作之后,发送者不应修改发送缓冲区的任何部分,直到发送完成为止。

我的代码如下:

// send messages
if(s > 0){

    MPI_Requests s_requests[s];
    MPI_Status   s_status[s];

    for(int i = 0; i < s; ++i){

        // some code to form the message to send
        std::vector<doubel> send_info;

        // non-blocking send
        MPI_Isend(&send_info[0], ..., s_requests[i]);
    }

    MPI_Waitall(s, s_requests, s_status);
}

// recv info
if(n > 0){    // s and n will match

    for(int i = 0; i < n; ++i){

        MPI_Status status;

        // allocate the space to recv info
        std::vector<double> recv_info;

        MPI_Recv(&recv_info[0], ..., status)
    }

}


[我的问题是:由于缓冲区位于内部大括号内,所以我是否要修改发送缓冲区(循环结束后send_info向量将被杀死)?因此,这不是一种安全的通信模式吗?尽管我的程序现在可以正常运行了,但我仍然被怀疑。谢谢您的回复。

c++ mpi nonblocking
1个回答
0
投票

在此示例中我要强调两点。

第一个是我问的问题:发送缓冲区在MPI_Waitall之前被修改。原因是吉尔斯说的。并且可以在for loop之前为解决方案分配一个大缓冲区,并在循环结束后使用MPI_Waitall或将MPI_Wait放入循环内。但是从性能的角度来看,后者相当于使用MPI_Send

但是,我发现如果您仅转换为阻止发送和接收,则这样的通信方案可能会导致死锁。它类似于经典的死锁:

if (rank == 0) {
      MPI_Send(..., 1, tag, MPI_COMM_WORLD);
      MPI_Recv(..., 1, tag, MPI_COMM_WORLD, &status);
 } else if (rank == 1) {
      MPI_Send(..., 0, tag, MPI_COMM_WORLD);
      MPI_Recv(..., 0, tag, MPI_COMM_WORLD, &status);
 }

并且可以在here中找到解释。

我的程序可能会导致类似的情况:所有被称为MPI_Send的处理器,这是一个死锁。

所以我的解决方案是使用大缓冲区并坚持使用非阻塞通信方案。

#include <vector>
#include <unordered_map>

// send messages
if(s > 0){

    MPI_Requests s_requests[s];
    MPI_Status   s_status[s];

    std::unordered_map<int, std::vector<double>> send_info;

    for(int i = 0; i < s; ++i){


        // some code to form the message to send
        send_info[i] = std::vector<double> ();

        // non-blocking send
        MPI_Isend(&send_info[i][0], ..., s_requests[i]);
    }

    MPI_Waitall(s, s_requests, s_status);
}

// recv info
if(n > 0){    // s and n will match

    for(int i = 0; i < n; ++i){

        MPI_Status status;

        // allocate the space to recv info
        std::vector<double> recv_info;

        MPI_Recv(&recv_info[0], ..., status)
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.