使用MPI_Send和MPI_Recv发送大型std :: vector无法完成

时间:2013-09-11 16:29:43

标签: mpi stdvector

我正在尝试使用MPI发送std :: vector。当向量很小时,这种方法很好,但是当向量很大时(向量中超过~15k的两倍),它才能正常工作。当尝试发送具有20k双精度的矢量时,程序就坐在那里,CPU处于100%。

这是一个最小的例子

#include <vector>
#include <mpi.h>

using namespace std;

vector<double> send_and_receive(vector<double> &local_data, int n, int numprocs, int my_rank) {
    MPI_Send(&local_data[0], n, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);

    if (my_rank == 0) {
        vector<double> global_data(numprocs*n);
        vector<double> temp(n);
        for (int rank = 0; rank < numprocs; rank++) {
            MPI_Recv(&temp[0], n, MPI_DOUBLE, rank, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
            for (int i = 0; i < n; i++) {
                global_data[rank*n + i] = temp[i];
            }
        }
        return global_data;
    }
    return vector<double>();
}

int main(int args, char *argv[]) {
    int my_rank, numprocs;
    // MPI initialization
    MPI_Init (&args, &argv);
    MPI_Comm_rank (MPI_COMM_WORLD, &my_rank);
    MPI_Comm_size (MPI_COMM_WORLD, &numprocs);

    int n = 15000;
    vector<double> local_data(n);

    for (int i = 0; i < n; i++) {
        local_data[i] = n*my_rank + i;
    }

    vector<double> global_data = send_and_receive(local_data, n, numprocs, my_rank);

    MPI_Finalize();

    return 0;
}

我使用

进行编译
mpic++ main.cpp

并使用

运行
mpirun -n 2 a.out

当我使用n = 15000运行时,程序成功完成,但是n = 17000n = 20000它永远不会完成,并且两个CPU处于100%,直到我强行关闭程序。< / p>

有谁知道问题可能是什么?

1 个答案:

答案 0 :(得分:2)

MPI_Send是一个有趣的电话。如果有足够的内部缓冲区来存储输入,那么可以返回 - 它唯一的保证是MPI不再需要输入缓冲区。但是,如果没有足够的内部缓冲区空间,则呼叫将阻塞,直到相反的MPI_Recv呼叫开始接收数据。看看这是怎么回事?由于缓冲区空间不足,两个进程都发布MPI_Send。在调试此类问题时,有助于将MPI_Send替换为MPI_Ssend

您可能的解决方案是:

  • 使用缓冲发送,MPI_Bsend
  • 使用MPI_Sendrecv
  • 备用发送/接收对,以便每个发送都有匹配的recv(例如,奇数proc发送,甚至recvs,反之亦然)。
  • 使用非阻止发送,MPI_Isend

请参阅http://www.netlib.org/utk/papers/mpi-book/node39.html