2012-11-17 30 views
3

我试图在这个简化的代码acheive是:(分别为根,和儿童,IDS /秩= 10和0-9)MPI_Irecv没有收到全部发送?

  • 2类型的过程
  • INIT:
    • 根会听“已完成”
    • 孩子会听根通知儿童在所有已完成
  • 虽然没有赢家(不是全部没有完成): 点
    • 的孩子将有20%的机会,他们将完成(并通知根他们这样做)
    • 根将检查全部弄完
      • 如果全部完成:发送通知的“胜利者”孩子

我有这样的代码:

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(); 

调试输出cout看起来像:问题似乎是根并没有收到他们完成的所有儿童通知?

2 sending to root 
3 sending to root 
0 sending to root 
4 sending to root 
1 sending to root 
8 sending to root 
9 sending to root 
numDone = 1 
numDone = 1 
... // many numDone = 1, but why 1 only? 
7 sending to root 
... 

我想也许我不能接收到一个数组:但我想

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; 
} 

其中一期工程。

UPDATE

这似乎可以解决,如果我在while循环结束前添加MPI_Barrier(MPI_COMM_WORLD),但是为什么呢?即使这些进程不同步,最终,孩子们会发送到root,他们已经完成,root应该“听”并相应地进行处理?似乎在发生的事情是,root一直在运行,占用了所有资源供儿童执行?或者这里发生了什么?

更新2:有些孩子不从根本得到通知

好了,现在根本没有收到,他们已经通过@ MichaelSh的回答完成儿童通知的问题,我专注于儿童无法从父母接受。下面是重现该问题的代码:

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 

注意某些进程似乎没有得到家长的通知?为什么呢,子进程的MPI_Wait只会挂住它们?那么我该如何解决这个问题?

而且

所有MPI_Barrier做你的情况 - 它等待孩子的反应来完成。请检查我的答案以获得更好的解决方案

如果我不这样做,我想每个孩子的回答只需几毫秒?所以,即使我不等待/屏障,我希望收到发送后不久仍然会发生?除非流程最终会占用资源,其他流程不会运行?

+0

可以跟踪多少次'MPI_Irecv(ARR [1] ...)'叫? –

+0

@MichaelSh,从代码来看,每次回合应该是10次(每个孩子一次)?我在irecv之后添加了一个cout并且足够真实,它被称为10次 –

+0

'MPI_Wait',在访问'arr'之前不必调用它。在你的例子中,你使用阻止发送/接收,但在你的应用程序中使用异步接收... –

回答

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++) { 
... 

编辑更好的解决方案:
每个孩子发起根赢家通知接收和发送其通知到根。
Root向阵列启动优胜者通知收据并进入等待接收的所有通知,然后将优胜者的ID发送给儿童。 插入下面这段代码后for (int round = 0; round < 1; round++)

  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; 
       } 
      }        
+0

嗯有道理,有点......可以有点令人困惑,......但现在似乎孩子们没有收到赢家的“通知”,因此继续处于无限循环,如果我试图等待循环根本不会进行(如预期)。 。 –

+0

确定更新后的帖子是“更新2”,重点关注这个问题 –

+0

我们是否应该在聊天中继续讨论? http://chat.stackoverflow.com/rooms/19666/discussion-between-jiew-meng-and-michael-sh? –