如何检查非阻塞减少的完成?

时间:2018-09-28 21:09:43

标签: mpi

我不清楚如何在MPI中正确使用非阻塞集合,在这种情况下尤其是MPI_Ireduce()

说我想从根目录中收集一笔款项:

int local_cnt;
int total_cnt;
MPI_Request request;
MPI_Ireduce(&local_cnt, &total_cnt, 1, MPI_INT, MPI_SUM, 0, MPI_WORLD_COMM, &request);

/* now I want to check if the reduce is finished */

if (rank == 0) {
    int flag = 0;
    MPI_Status status;
    MPI_Test(&request, &flag, &status);
    if (flag) {
        /* reduce is finished? */
    }
}

这是检查是否完成非阻塞归约的正确方法吗?我的困惑来自两个方面:一,是否可以使用MPI_Test()进行根进程检查,因为这仅对根有意义?其次,由于MPI_Test()是本地操作,因此该本地操作如何知道操作已完成?它确实需要完成所有过程,对吧?

2 个答案:

答案 0 :(得分:1)

您必须检查所有参与等级的完成情况,而不仅仅是根。

从用户的角度出发,您需要了解通信的完成情况,因为您不得对非阻塞操作提供的内存进行任何操作。即如果您发送local_cnt之类的本地范围变量,则在确认操作已完成之前,无法对其进行写入或保留其范围。

确保完成的一种方法是调用MPI_Test,直到最终返回flag==true。仅当您可以在调用MPI_Test之间进行一些有用的操作时,才使用此功能:

{
    int local_cnt;
    int total_cnt;

    // fill local_cnt on all ranks

    MPI_Request request;
    MPI_Ireduce(&local_cnt, &total_cnt, 1, MPI_INT, MPI_SUM, 0, MPI_WORLD_COMM, &request);

    int flag;
    do {

        // perform some useful computation
        MPI_Status status;
        MPI_Test(&request, &flag, &status);
    } while (!flag)
}

如果两次调用之间没有任何用处,请不要循环调用MPI_Test。而是使用MPI_Wait,它会阻塞直到完成。

{
    int local_cnt;
    int total_cnt;

    // fill local_cnt on all ranks

    MPI_Request request;
    MPI_Ireduce(&local_cnt, &total_cnt, 1, MPI_INT, MPI_SUM, 0, MPI_WORLD_COMM, &request);

    // perform some useful computation
    MPI_Status status;
    MPI_Wait(&request, &status);
}

请记住,如果您根本没有有用的计算,并且由于死锁原因不需要非阻塞,请首先使用阻塞通信。如果您有多个正在进行的非阻塞通信,则有MPI_WaitanyMPI_WaitsomeMPI_Waitall及其测试变体。

答案 1 :(得分:1)

祖兰妙妙地回答了您问题的第一部分。

MPI_Reduce()返回时间

  • 发送缓冲区可以在非根目录上覆盖
  • 结果在根排名上可用(这意味着所有等级均已完成)

因此,非根级别无法知道根级别是否已完成。如果确实需要此信息,则需要手动添加MPI_Barrier()。话虽如此,您通常需要此信息,并且如果您认为确实需要此信息,则您的应用可能存在问题。

如果您使用非阻塞集合(例如,与MPI_Wait()对应的MPI_Ireduce()在非根目录级别上完成),则情况仍然如此:这仅意味着发送缓冲区可以被覆盖。