在新的MPI_Isend之前使用MPI_Wait

时间:2018-05-21 14:17:40

标签: c++ mpi

我试图使用MPI_Wait阻止之前可能会或可能没有调过的MPI_Isend,但它似乎没有阻止下一个MPI_Isend。

基本上如果之前已经调用了MPI_Isend但没有收到,那么我想等到收到它。然后调用一个新的MPI_Isend。每个进程都应始终探测传入的消息并动态接收它们。

for (time_stamp=0; time_stamp<time_max; time_stamp++) { // for each time stamp

    // Probe for incoming particles from any process
    MPI_Iprobe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &flag, &statRec);

    // Receive particles from a process
    if(flag){
        std::cout << "Recieved from rank: " << statRec.MPI_SOURCE <<  "\n";
        int recCount{};
        MPI_Get_count(&statRec, MPI_Particle, &recCount);
        Particle *recbuf = new Particle[recCount];
        MPI_Recv(recbuf, recCount, MPI_Particle, statRec.MPI_SOURCE, statRec.MPI_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        for(int i=0; i<recCount; i++)
            Particles.emplace_back(recbuf[i]);

        delete[] recbuf;
    }

    int n = (int)Particles.size(), totalp = 0;
    MPI_Reduce(&n, &totalp,  1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
    if(rank == root)
        std::cout << "Total particles "  << totalp << "\n";

    /* Do particle operations, put them in sendlists
       and delete them from this ranks own particle list.... */

    // Send to another process
    if(!sendParticles.empty()) {
        MPI_Wait(&req, MPI_STATUS_IGNORE);
        std::cout << "Sending from rank " << rank << "... \n" ;
        delete[] sendBuf;
        sendcount = static_cast<int>(sendParticles.size());
        sendBuf = new Particle[sendcount];
        for(int i=0; i<sendParticles.size(); i++)
            sendBup[i] = sendParticles[i];

        MPI_Isend(sendBuf, sendcount, MPI_Particle, some_other_rank, 0, MPI_COMM_WORLD, &req);
    }
}

输出:
总颗粒1000
从等级1发送...
从等级0发送...
总颗粒998
从等级1发送...
从等级0发送...
获得排名:1
总颗粒994
从等级1发送...
摘自等级:0
从等级0发送...
获得排名:1
总颗粒993
从等级0发送...
获得排名:1
总颗粒993
从等级1发送...
从0级发送......

如您所见,它尝试连续两次发送两个进程,忽略MPI_Wait。它似乎也一直在减少到粒子的总数,我猜测它会因为它不会等待而覆盖sendbuffer而丢失。

(对代码进行了一些编辑以使其更具可读性)

1 个答案:

答案 0 :(得分:1)

如果您对来自前一个MPI_Wait()的请求发出MPI_ISend(),则会阻止,直到可以重复使用发送缓冲区。

从一个非常简单的角度来看,如果消息足够短,它将立即返回,并挂起,否则将发布匹配的接收。 (足够短取决于您的MPI库,互连和其他因素。请注意,您永远不应理所当然MPI_Wait()将立即返回小消息。

您的说明建议您需要将MPI_Isend()替换为MPI_Issend()

请注意,当发布匹配的接收时,标准仅强制MPI_Wait()返回,严格地说,它可能会在远程对等方完全接收到消息之前返回。