其他进程在MPI_Sendrecv之后挂起

时间:2012-11-09 11:03:44

标签: c++ openmpi

我认为使用MPI_Sendrecv

MPI_Sendrecv(&ballPos, 2, MPI_INT, FIELD, NEW_BALL_POS_TAG, &ballPos, 2, MPI_INT, winner, NEW_BALL_POS_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

但我注意到只有根(接收方继续运行?)。在Sendrecv之前和之后生成cout

0 b4 sendrecv
2 b4 sendrecv
4 b4 sendrecv
1 b4 sendrecv
3 b4 sendrecv
5 b4 sendrecv
0 after sendrecv

在sendrecv之前所有进程都正常,但之后只有root解除阻塞。

Full source:见第147行

更新

结果应该类似于下面的内容

if (rank == winner) {
    ballPos[0] = rand() % 128;
    ballPos[1] = rand() % 64;
    cout << "new ball pos: " << ballPos[0] << " " << ballPos[1] << endl;
    MPI_Send(&ballPos, 2, MPI_INT, FIELD, NEW_BALL_POS_TAG, MPI_COMM_WORLD);
} else if (rank == FIELD) {
    MPI_Recv(&ballPos, 2, MPI_INT, winner, NEW_BALL_POS_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}

1 个答案:

答案 0 :(得分:1)

发布的发送数量应该等于发布的发送数量。在您的情况下,所有排名都会发送到排名FIELD并从排名winner收到,包括FIELDwinner

Rank       Sends to  Receives from
----------------------------------
0 (FIELD)  FIELD     winner
1          FIELD     winner
2          FIELD     winner
...        ...       ...
winner     FIELD     winner
...        ...       ...
numprocs-1 FIELD     winner

(有时候这些表非常有用)

因此,FIELD应该会收到numprocs条消息,但它只会执行一次MPI_Sendrecv,因此对numprocs-1的{​​{1}}次呼叫将无法完成其发送。 MPI_Sendrecv也是如此。它应该发送winner消息,但由于它只执行numprocs一次,因此只发送一条消息,因此MPI_Sendrecvnumprocs-1的调用将无法完成其接收。< / p>

还有另一个错误。 MPI标准要求发送和接收缓冲区不相交(即它们不应重叠),这与您的代码不同。您的发送和接收缓冲区不仅重叠,而且它们是同一个缓冲区。如果要在同一缓冲区中执行交换,MPI将提供MPI_Sendrecv操作。

我不确定您要使用此MPI_Sendrecv_replace语句尝试实现的目标,但我强烈怀疑您需要将其置于MPI_Sendrecv语句中。