我试图在这个简化的代码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
做你的情况 - 它等待孩子的反应来完成。请检查我的答案以获得更好的解决方案
如果我不这样做,我想每个孩子的回答只需几毫秒?所以,即使我不等待/屏障,我希望收到发送后不久仍然会发生?除非流程最终会占用资源,其他流程不会运行?
可以跟踪多少次'MPI_Irecv(ARR [1] ...)'叫? –
@MichaelSh,从代码来看,每次回合应该是10次(每个孩子一次)?我在irecv之后添加了一个cout并且足够真实,它被称为10次 –
'MPI_Wait',在访问'arr'之前不必调用它。在你的例子中,你使用阻止发送/接收,但在你的应用程序中使用异步接收... –