调用MPI_Recv挂起

时间:2014-02-27 20:16:16

标签: c parallel-processing mpi

为了简单起见,发送信息发送到排名+ 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的调用。有人看到这个有问题吗?我错过了什么?

由于

2 个答案:

答案 0 :(得分:1)

当您调用MPI_Isend时,传入的最后一个参数(并返回)是MPI_Request个对象。您对MPI_Isend的初始调用没有(必要)执行发送本身。它只是通知MPI您希望在现在和完成该请求之间的某个时间执行发送操作。要表明您要完成请求,您需要对完成功能(例如MPI_WaitMPI_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 - 问题就解决了。

相关问题