使用MPI_Irecv和MPI_Test的无限循环

我在C中使用MPI程序时遇到了一些问题。我想发送MPI_Send从从站到主站(使用MPI_Send,MPI_Irecv和MPI_Test)的两条消息,但只有第一条消息有效。之后,我有一个无限循环,我总是收到来自slave的消息-1(根据status.MPI_Source)。使用MPI_Irecv和MPI_Test的无限循环

,所以我不明白为什么我收到一个未知的过程(-1),所有这些消息......

我的代码:

#include <stdio.h> 

#include <mpi.h>

#include <sys/time.h>

int main(int argc, char *argv[])

{

int rank, size;

MPI_Status status;

/* Init */

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

if (rank != 0) { // Slaves

int buf;

if (rank == 1) {

buf = 1;

MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);

}

if (rank == 2) {

buf = 2;

MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);

}

}

else { // Master

int sum = 0;

int flag, res;

MPI_Request request;

MPI_Status status;

MPI_Irecv(&res, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &request);

while (1) {

flag = 0;

MPI_Test(&request, &flag, &status);

if (flag != 0) {

printf("recv : %d, slave : %d\n", res, status.MPI_SOURCE);

if (status.MPI_SOURCE != -1)

sum += res;

}

else

printf("fail!\n");

if (sum == 3)

break;

}

printf("sum : %d\n", sum);

}

MPI_Finalize();

return 0;

}

感谢。

ps:对不起,我的英语

回答:

问题是,主人只发布一个接收。您需要将呼叫转移到循环内的MPI_Irecv,此时MPI_Test成功返回(位于if (status.MPI_SOURCE != -1)块内),以便可以接收后续消息。

回答:

有一件事是,您每次需要消息时都必须调用MPI_Irecv。所以在你的情况下,你必须调用它2次。没有更多,不少。

让我们看看仅通过在循环内移动MPI_Irecv调用而改变的代码。 这是不正确的。不管用。

else { // Master 

int sum = 0;

int flag, res;

MPI_Request request;

MPI_Status status;

while (1) {

flag = 0;

MPI_Irecv(&res, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &request);

MPI_Test(&request, &flag, &status);

if (flag != 0) {

printf("recv : %d, slave : %d\n", res, status.MPI_SOURCE);

if (status.MPI_SOURCE != -1)

sum += res;

}

else

printf("fail!\n");

if (sum == 3)

break;

}

假设提供由奴隶sended消息的随机时间(这始终是当我们谈论分布式系统或线程的情况下),可以很容易地想象这种情况: 时刻的时间|事件

0    | called first MPI_Irecv, allocated memory for MPI_Request object 

1 | called second MPI_Irecv, allocated memory for MPI_Request (lets say) object2

2 | called third MPI_Irecv, allocated memory for MPI_Request object3

3 | called MPI_Send in slave no. 1

4 | called MPI_Send in slave no. 2

5 | received message by master from slave no. 1, filled object, flag variable still 0 because its related to object3

6 | received message by master from slave no. 2, filled object2, flag variable still 0 because its related to object3

7,8,9... | infinite loop, flag still has value 0

n | error: MPI_Irecv(147): MPI_Irecv(buf=0x7fffecfa60c4, count=1, MPI_INT, src=MPI_ANY_SOURCE, tag=MPI_ANY_TAG, MPI_COMM_WORLD, request=0x7fffecfa60c8)

MPID_Irecv(53): failure occurred while allocating memory for a request object

有两种解决方案。您可以通过在while循环之前调用sleep(3)来减慢主进程,所以它肯定会在稍后调用MPI_Send的时候启动。

其次,更好的工程方法是只在我们期待消息时调用MPI_Irecv。最初调用MPI_Irecv并将值赋给该标志。在我们将消息更改标志再次接收到-1后,仅当标志具有-1值时才调用MPI_Irecv。

这里是代码它的工作原理:

#include <stdio.h> 

#include <mpi.h>

#include <sys/time.h>

int main(int argc, char *argv[])

{

int rank, size;

MPI_Status status;

/* Init */

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

if (rank != 0) { // Slaves

int buf;

if (rank == 1) {

buf = 1;

MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);

}

if (rank == 2) {

buf = 2;

MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);

}

}

else { // Master

int sum = 0;

int flag = -1, res;

MPI_Request request;

MPI_Status status;

while (1) {

if(flag != 0)

{

MPI_Irecv(&res, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &request);

flag = 0;

}

MPI_Test(&request, &flag, &status);

if (flag != 0) {

printf("recv : %d, slave : %d\n", res, status.MPI_SOURCE);

if (status.MPI_SOURCE != -1)

sum += res;

flag = -1;

}

if (sum == 3)

break;

}

printf("sum : %d\n", sum);

}

MPI_Finalize();

return 0;

}

以上是 使用MPI_Irecv和MPI_Test的无限循环 的全部内容, 来源链接: utcz.com/qa/265045.html

回到顶部