MPI发送和接收(多对多)

时间:2014-04-17 18:38:18

标签: c mpi

我有以下代码现在可以使用,但我不认为随着进程数和发送数据的增长而扩展。

以下是我要去的地方:

首先,我有一个发送循环,每个处理器互相发送消息。 每个进程发送的消息长度将不同,但不是类型。

 for (int i = 0; i < n_proc; ++i){
     if (i != my_rank){
           int N = Xcoord_top[my_rank].size();
           MPI_Send(&Xcoord_top[my_rank][0], N, MPI_DOUBLE, i, 1000, MPI_COMM_WORLD);
     }
 }
 MPI_Barrier(MPI_COMM_WORLD);

我发送消息后,我使用类似的循环

收到消息
for (int i = 0; i < n_proc; ++i){
    if (i != my_rank){
         std::vector<double> temp(max_n);
         MPI_Recv(&temp[0], points_per_proc[i], MPI_DOUBLE,
                    MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
         ...
    }
}

在第二个循环中,我也有几行根据标签和来源将消息放在正确的位置

只有当我将障碍放在循环之间时才会起作用,否则会崩溃。

根据我的理解,消息的MPI内部存储可能会溢出(我不确定我是否使用了正确的术语)。因此,在这种情况下,程序将在第一个循环期间挂起。

我应该怎么做呢?

1 个答案:

答案 0 :(得分:2)

有点太多代码无法容纳评论:

我建议只将其作为一个MPI_Allgatherv()

std::vector<int> disps(n_proc);

disps[0] = 0;
for (int i=1; i<n_proc; i++)
  disps[i] = disps[i-1] + points_per_proc[i-1];

int totdata = disps[n_proc-1] + points_per_proc[n_proc-1];
std::vector<double> temp(totdata);

MPI_Allgatherv(&Xcoord_top[my_rank][0], Xcoord_top[my_rank].size(),
               MPI_Double, temp, points_per_proc, disps, MPI_DOUBLE,
               MPI_COMM_WORLD);

现在,proc i的数据位于temp[disps[i]]...temp[disps[i+1]-1]

最初发布的代码至少存在三个问题:

  • 它可能很好地死锁(发送被允许阻止直到收到) - 这可以通过使用异步发送来修复,例如MPI_Isend()使用以下MPI_Waitall()而不是MPI_Send();
  • 它几乎肯定会无序地处理接收(不能保证在第i次迭代中它从第i个处理器接收),因此消息长度可能是错误的,导致错误将中止该计划 - 可以通过将来源修改为排名i而不是MPI_ANY_SOURCE来修复;和
  • 效率低,使用线性点对点发送和接收而不是广播或收集等优化集体 - 可以通过使用集合来修复,例如allgather,如上所述。