我认为使用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);
}

最佳答案

发送的发送数量应等于发送的接收数量。在您的情况下,所有等级都发送到等级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-1MPI_Sendrecv调用将无法完成其发送。 winner也是如此。它应该发送numprocs消息,但由于它仅执行一次MPI_Sendrecv,因此仅发送一条消息,因此对numprocs-1MPI_Sendrecv调用将无法完成其接收。

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

我不确定您要使用此MPI_Sendrecv语句实现什么目的,但是我强烈怀疑您需要将其放入if语句中。

10-08 11:06