Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ MPI_Irecv未接收所有发送?_C++_Openmpi - Fatal编程技术网

C++ MPI_Irecv未接收所有发送?

C++ MPI_Irecv未接收所有发送?,c++,openmpi,C++,Openmpi,在这段简化的代码中,我试图实现的是: 2种类型的进程(根进程和子进程,分别为id/rank=10和0-9) 初始化: root将侦听子级“已完成” 所有操作完成后,子级将侦听根通知 虽然没有赢家(尚未全部完成): 孩子们有20%的机会完成(并通知root他们完成) root将检查所有操作是否完成 如果全部完成:向“获胜者”的子女发送通知 我有如下代码: int numprocs, id, arr[10], winner = -1; bool stop = false; MPI_R

在这段简化的代码中,我试图实现的是:

  • 2种类型的进程(根进程和子进程,分别为id/rank=10和0-9)
  • 初始化:
    • root将侦听子级“已完成”
    • 所有操作完成后,子级将侦听根通知
  • 虽然没有赢家(尚未全部完成):
    • 孩子们有20%的机会完成(并通知root他们完成)
    • root将检查所有操作是否完成
      • 如果全部完成:向“获胜者”的子女发送通知
我有如下代码:

int numprocs, id, arr[10], winner = -1;
bool stop = false;
MPI_Request reqs[10], winnerNotification;

MPI_Init(NULL, NULL);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &id);

for (int half = 0; half < 1; half++) {
    for (int round = 0; round < 1; round++) {
        if (id == 10) { // root
            // keeps track of who has "completed"
            fill_n(arr, 10, -1);
            for (int i = 0; i < 10; i++) {
                MPI_Irecv(&arr[i], 1, MPI_INT, i, 0, MPI_COMM_WORLD, &reqs[i]);
            }
        } else if (id < 10) { // children
            // listen to root of winner notification/indication to stop
            MPI_Irecv(&winner, 1, MPI_INT, 10, 1, MPI_COMM_WORLD, &winnerNotification);
        }

        while (winner == -1) {
            //cout << id << " is in loop" << endl;

            if (id < 10 && !stop && ((rand() % 10) + 1) < 3) { 
                // children has 20% chance to stop (finish work)
                MPI_Send(&id, 1, MPI_INT, 10, 0, MPI_COMM_WORLD);
                cout << id << " sending to root" << endl;
                stop = true;
            } else if (id == 10) {
                // root checks number of children completed
                int numDone = 0;
                for (int i = 0; i < 10; i++) {
                    if (arr[i] >= 0) {
                        //cout << "root knows that " << i << " has completed" << endl;
                        numDone++;
                    }
                }
                cout << "numDone = " << numDone << endl;

                // if all done, send notification to players to stop
                if (numDone == 10) {
                    winner = 1;
                    for (int i = 0; i < 10; i++) {
                        MPI_Send(&winner, 1, MPI_INT, i, 1, MPI_COMM_WORLD);
                    }
                    cout << "root sent notification of winner" << endl;
                }
            }
        }
    }
}

MPI_Finalize();
我想也许我无法接收到一个数组,但我尝试了

if (id == 1) {
    int x = 60;
    MPI_Send(&x, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
} else if (id == 0) {
    MPI_Recv(&arr[1], 1, MPI_INT, 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    cout << id << " recieved " << arr[1] << endl;
}
输出如下所示:

# 1 run
winner notifications sent
10 b4 MPI_Finalize. winner is 2
9 b4 MPI_Finalize. winner is 2
0 b4 MPI_Finalize. winner is 2

# another run
winner notifications sent
10 b4 MPI_Finalize. winner is 2
8 b4 MPI_Finalize. winner is 2
请注意,有些进程似乎没有收到来自父进程的通知?为什么,
MPI_Wait
子进程只会挂起它们?那么我该如何解决这个问题呢


在您的情况下,MPI\U屏障的所有功能都会执行—它等待子级响应完成。请检查我的答案,寻找更好的解决方案


如果我不这样做,我想每个孩子的回答只需要几毫秒?因此,即使我不等待/设置障碍,我也希望在发送后不久仍能收到?除非进程最终占用资源,而其他进程不运行

请尝试此代码块(为了简单起见,省略了错误检查):

。。。
//根目录检查已完成的子目录数
int numDone=0;
MPI_状态[10];
MPI_Waitall(10,需求,状态);
对于(int i=0;i<10;i++){
...
编辑更好的解决方案:
每个子级启动根赢家通知接收,并将其通知发送给根。
Root向阵列发送赢家通知接收,并进入等待接收所有通知的状态,然后将赢家的id发送给子级。 在(int round=0;round<1;round++)的
后面插入以下代码

if(id==10)
{//根
//跟踪谁已“完成”
memset(arr,-1,sizeof(arr));
对于(int i=0;i<10;i++)
{
MPI_Irecv(&arr[i],1,MPI_INT,i,0,MPI_COMM_WORLD,&reqs[i]);
}
} 
否则,如果(id<10)
{//儿童
//聆听赢家通知/指示停止的根目录
MPI_Irecv(冠军、1名、MPI_INT、10名、1名、MPI_COMM_WORLD和winnerNotification);
}
如果(id<10)
{
而(((rand()%10)+1)<3);
//儿童有20%的机会停止(完成工作)
MPI_发送(&id,1,MPI_INT,10,0,MPI_COMM_WORLD);

std::你能追踪一下调用了多少次
MPI_-Irecv(&arr[i],…)
吗?@MichaelSh,根据代码,应该是10次(每个孩子一次),对于每一轮?我在irecv之后添加了一个cout,没错,它被称为10次。关于
MPI\u Wait
,在访问
arr
之前你不需要调用它吗?在你的例子中,你使用阻塞发送/接收,但在你的应用中你使用异步接收…嗯…我想问题是我真的不想“等待”,如果有不完整的进程,我需要循环继续(如果我等待,循环将不会继续?).我的印象是,根检查每个循环上的arr应该可以工作?这意味着在某个时间点,arr应该填充来自已完成的
Irecv
?所有
MPI_屏障在您的情况下都可以-它会等待子响应完成。请检查我的答案,以获得更好的解决方案。嗯,有意义,有点。。。可能有点混乱,…但现在孩子们似乎没有收到赢家的“通知”,因此继续处于无限循环中,如果我尝试等待,循环将根本不会继续(如预期的那样)…我们是否应该在聊天中继续讨论??(为了简单起见,省略了错误检查)。实际上,检查简单MPI程序中的错误是毫无意义的,因为MPI标准要求默认错误处理程序中止程序执行。因此,MPI调用return
MPI\u SUCCESS
或干脆不返回(当程序终止时)。必须将每个通信器的错误处理程序显式更改为
MPI\u ERRORS\u RETURN
,以便从失败的调用中接收MPI状态代码。
int numprocs, id, arr[10], winner = -1;
bool stop = false;
MPI_Request reqs[10], winnerNotification;

MPI_Init(NULL, NULL);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &id);

srand(time(NULL) + id);

if (id < 10) {
    MPI_Irecv(&winner, 1, MPI_INT, 10, 0, MPI_COMM_WORLD, &winnerNotification);
}
MPI_Barrier(MPI_COMM_WORLD);

while (winner == -1) {
    cout << id << " is in loop ..." << endl;
    if (id == 10) {
        if (((rand() % 10) + 1) < 2) {
            winner = 2;
            for (int i = 0; i < 10; i++) {
                MPI_Send(&winner, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
            }
            cout << "winner notifications sent" << endl;
        }
    }
}

cout << id << " b4 MPI_Finalize. winner is " << winner << endl;

MPI_Finalize();
# 1 run
winner notifications sent
10 b4 MPI_Finalize. winner is 2
9 b4 MPI_Finalize. winner is 2
0 b4 MPI_Finalize. winner is 2

# another run
winner notifications sent
10 b4 MPI_Finalize. winner is 2
8 b4 MPI_Finalize. winner is 2
...
// root checks number of children completed
int numDone = 0;
MPI_Status statuses[10];
MPI_Waitall(10, reqs, statuses);
for (int i = 0; i < 10; i++) {
...
            if (id == 10) 
            { // root
                // keeps track of who has "completed"
                memset(arr, -1, sizeof(arr));
                for (int i = 0; i < 10; i++) 
                {
                    MPI_Irecv(&arr[i], 1, MPI_INT, i, 0, MPI_COMM_WORLD, &reqs[i]);
                }
            } 
            else if (id < 10) 
            { // children
                // listen to root of winner notification/indication to stop
                MPI_Irecv(&winner, 1, MPI_INT, 10, 1, MPI_COMM_WORLD, &winnerNotification);
            }

            if (id < 10)
            {
                while(((rand() % 10) + 1) < 3) ;

                // children has 20% chance to stop (finish work)
                MPI_Send(&id, 1, MPI_INT, 10, 0, MPI_COMM_WORLD);
                std::cout << id << " sending to root" << std::endl;
                // receive winner notification
                MPI_Status status;
                MPI_Wait(&winnerNotification, &status);
                // Process winner notification
            } 
            else if (id == 10) 
            {
                MPI_Status statuses[10];
                MPI_Waitall(10, reqs, statuses);                    

                // if all done, send notification to players to stop
                {
                    winner = 1;
                    for (int i = 0; i < 10; i++) 
                    {
                        MPI_Send(&winner, 1, MPI_INT, i, 1, MPI_COMM_WORLD);
                    }
                    std::cout << "root sent notification of winner" << std::endl;
                }
            }