gpt4 book ai didi

c - 使用 MPI_Irecv 和 MPI_Test 的无限循环

转载 作者:太空狗 更新时间:2023-10-29 14:51:56 25 4
gpt4 key购买 nike

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

所以我不明白为什么我会收到来自未知进程 (-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。所以在你的情况下你必须调用它 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;
}

假设随机时间传递从属发送的消息(当我们谈论分布式系统或线程时总是这样)很容易想象这种情况:时刻 |事件

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) 来减慢 Master 进程,因此它肯定会在调用 MPI_Send 之后启动。

其次,更好的工程方法是仅在我们期待消息时调用 MPI_Irecv。最初调用 MPI_Irecv 并将值 0 分配给标志。在我们收到消息后,再次将标志更改为 -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;

}

关于c - 使用 MPI_Irecv 和 MPI_Test 的无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15095514/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com