使用MPI_Irecv和MPI_测试的无限循环

使用MPI_Irecv和MPI_测试的无限循环,c,mpi,C,Mpi,我对C语言中的MPI程序没有什么问题。我想用MPI_send从从机发送两条消息到主机(使用MPI_send、MPI_Irecv和MPI_Test),但只有第一条消息有效。之后,我有一个无限循环,我总是从slave-1(根据status.MPI_Source)接收消息 所以我不明白为什么我从一个未知进程(-1)收到所有这些消息 我的代码: #include <stdio.h> #include <mpi.h> #include <sys/time.h> int

我对C语言中的MPI程序没有什么问题。我想用MPI_send从从机发送两条消息到主机(使用MPI_send、MPI_Irecv和MPI_Test),但只有第一条消息有效。之后,我有一个无限循环,我总是从slave-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;

}
#包括
#包括
#包括
int main(int argc,char*argv[])
{
int等级、大小;
MPI_状态;
/*初始化*/
MPI_Init(&argc,&argv);
MPI通信等级(MPI通信世界和等级);
MPI_通信大小(MPI_通信世界和大小);
如果(秩!=0){//
int buf;
如果(秩==1){
buf=1;
MPI_发送(&buf,1,MPI_INT,0,0,MPI_COMM_WORLD);
}
如果(秩==2){
buf=2;
MPI_发送(&buf,1,MPI_INT,0,0,MPI_COMM_WORLD);
}
}
否则{//Master
整数和=0;
国际旗帜;
MPI_请求;
MPI_状态;
MPI_Irecv(&res,1,MPI_INT,MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&request);
而第(1)款{
flag=0;
MPI_测试(请求、标志和状态);
如果(标志!=0){
printf(“recv:%d,slave:%d\n”,res,status.MPI\u SOURCE);
如果(status.MPI_SOURCE!=-1)
sum+=res;
}
其他的
printf(“失败!\n”);
如果(总和=3)
打破
}
printf(“总和:%d\n”,总和);
}
MPI_Finalize();
返回0;
}
谢谢


ps:对不起,我的英语不好,问题是大师只发过一次回帖。您需要将调用移动到循环内的
MPI\u Irecv
,在
MPI\u Test
成功返回的位置(在
if(status.MPI\u SOURCE!=-1)
块内),以便可以接收后续消息。

一件事是,每次需要消息时都必须调用MPI\u Irecv。所以在你的情况下,你必须打两次电话。不多也不少

让我们看一看仅在循环内移动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)来降低主进程的速度,所以它肯定会在调用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;

}
#包括
#包括
#包括
int main(int argc,char*argv[])
{
int等级、大小;
MPI_状态;
/*初始化*/
MPI_Init(&argc,&argv);
MPI通信等级(MPI通信世界和等级);
MPI_通信大小(MPI_通信世界和大小);
如果(秩!=0){//
int buf;
如果(秩==1){
buf=1;
MPI_发送(&buf,1,MPI_INT,0,0,MPI_COMM_WORLD);
}
如果(秩==2){
buf=2;
MPI_发送(&buf,1,MPI_INT,0,0,MPI_COMM_WORLD);
}
}
否则{//Master
整数和=0;
int flag=-1,res;
MPI_请求;
MPI_状态;
而第(1)款{
如果(标志!=0)
{
MPI_Irecv(&res,1,MPI_INT,MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&request);
flag=0;
}
MPI_测试(请求、标志和状态);
如果(标志!=0){
printf(“recv:%d,slave:%d\n”,res,status.MPI\u SOURCE);
如果(status.MPI_SOURCE!=-1)
sum+=res;
flag=-1;
}
如果(总和=3)
打破
}
printf(“总和:%d\n”,总和);
}
MPI_Finalize();
返回0;
}