为了简单起见,发送信息发送到排名+ 1,发送信息发送到排名-1
代码在它们之间来回传递数组从一个节点到另一个节点。这是代码:
MPI_Request req1, req2;
MPI_Status s1, s2;
if (procid+1 != nproc) {
// send up
MPI_Isend(prior_hot_plate[my_num_rows-2], TOTAL_COLS, MPI_FLOAT, procid+1, k, MPI_COMM_WORLD, &req1);
++k;
fprintf(stderr, "%d made it through Isend up\n", procid);
}
if (procid-1 != -1) {
// send down
MPI_Isend(prior_hot_plate[1], TOTAL_COLS, MPI_FLOAT, procid-1, k, MPI_COMM_WORLD, &req2);
++k;
fprintf(stderr, "%d made it past Isend down\n", procid);
}
if (procid+1 != nproc) {
// recv up
//MPI_Wait(&req1, &s1);
//fprintf(stderr, "%d finished wait\n", procid);
MPI_Recv(prior_hot_plate[my_num_rows-1], TOTAL_COLS, MPI_FLOAT, procid+1, k, MPI_COMM_WORLD, &s1);
++k;
fprintf(stderr, "%d finished receiving\n", procid);
}
if (procid-1 != -1) {
// recv down
//MPI_Wait(&req2, &s2);
//fprintf(stderr, "%d finished wait\n", procid);
MPI_Recv(prior_hot_plate[0], TOTAL_COLS, MPI_FLOAT, procid-1, k, MPI_COMM_WORLD, &s2);
++k;
fprintf(stderr, "%d finished receiving\n", procid);
}
每个节点都通过Isend调用没问题,但是所有这些节点都挂起了对Recv的调用。有人看到这个有问题吗?我错过了什么?
由于
答案 0 :(得分:1)
当您调用MPI_Isend
时,传入的最后一个参数(并返回)是MPI_Request
个对象。您对MPI_Isend
的初始调用没有(必要)执行发送本身。它只是通知MPI您希望在现在和完成该请求之间的某个时间执行发送操作。要表明您要完成请求,您需要对完成功能(例如MPI_Wait
或MPI_Test
)进行匹配调用。
还有其他问题也包括这个问题(例如here)。
对于您的特定问题,正确的做法是将您的所有通信转换为非阻止调用,然后在底部执行大型MPI_Waitall
:
MPI_Request reqs[] = {MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL};
if (procid+1 != nproc) {
// send up
MPI_Isend(prior_hot_plate[my_num_rows-2], TOTAL_COLS, MPI_FLOAT, procid+1, k, MPI_COMM_WORLD, &reqs[0]);
}
if (procid-1 != -1) {
// send down
MPI_Isend(prior_hot_plate[1], TOTAL_COLS, MPI_FLOAT, procid-1, k, MPI_COMM_WORLD, &reqs[1]);
}
if (procid+1 != nproc) {
// recv up
MPI_Irecv(prior_hot_plate[my_num_rows-1], TOTAL_COLS, MPI_FLOAT, procid+1, k, MPI_COMM_WORLD, &reqs[2]);
}
if (procid-1 != -1) {
// recv down
MPI_Irecv(prior_hot_plate[0], TOTAL_COLS, MPI_FLOAT, procid-1, k, MPI_COMM_WORLD, &reqs[3]);
}
++k;
MPI_Waitall(4, reqs, MPI_STATUSES_IGNORE);
答案 1 :(得分:0)
我找到了答案。我尝试过韦斯利的方法,但我无法让它发挥作用。它只是保持segfaulting。然而他的例子让我最终改变了我的代码。在原始版本中,我在每次调用send和recv之后递增k,即标记。因此,recv调用正在寻找带有错误标记的消息。通过将其切换到韦斯利的方式 - 在最后增加k - 问题就解决了。