ale
ale

Reputation: 11830

Simple MPI question - receive from any process IF there is a message waiting to be picked up

In C, I have a message that a process may or may not broadcast to all the other processes:

MPI_Bcast(outmsg, 128, MPI_CHAR, 0, MPI_COMM_WORLD);

but I want the other processes to check for a message every now and again. I don't want them to do any waiting if there is no message - they can carry on with their computation and try again after some more computation.

Any ideas? Thank you :).

Upvotes: 1

Views: 3108

Answers (2)

JimBamFeng
JimBamFeng

Reputation: 749

There is a better example, the important point is to check with MPI_Iprobe() several times:

#include "mpi.h"
#include <cstdlib>
#include <vector>
#include <iostream>

using namespace std;

int main(int argc, char **argv)
{

    int myrank,size;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
    MPI_Comm_size(MPI_COMM_WORLD,&size);

    vector<int> destination;

    if(myrank==0)
    {
        destination.push_back(1);
    }
    else if(myrank==1)
    {
        destination.push_back(0);
    }


    for(uint i=0; i < destination.size(); i++)
    {
        //cout << myrank << " " << destination.at(i) << endl;
    }

    MPI_Status status;
    MPI_Request request;

    int rcvbuff;
    //int buff[2]
    int sendbuff=myrank+10;
    for(uint i=0;i<destination.size() ;i++)
    {
        MPI_Isend(&sendbuff,1,MPI_INT, destination.at(i),0, MPI_COMM_WORLD, &request);

    }

    int count;
    int flag=0;
    while(flag==0)
    {
        MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag,&status);
        cout << "Process " << myrank << ", flag " << flag << endl;
    }
    if(flag)
    {
        MPI_Get_count(&status, MPI_INT, &count);
        MPI_Irecv(&rcvbuff,count, MPI_INT,destination.at(0),0, MPI_COMM_WORLD, &request);
    }

    /*    enter code here     */

    MPI_Wait(&request,&status);

    cout << "The message received by " << myrank << " is '" << rcvbuff << "'" << endl;

    MPI_Finalize();
}

Upvotes: 1

osgx
osgx

Reputation: 94255

You may use MPI_Iprobe to check for message in "inbox" and if the check success, get the message with MPI_Recv. But with Iprobe you can't use a Bcast and you should switch to manual MPI_Isend with manual looping over communicator. Also add MPI_Wait() after Isend. Here is an example for two processes (but sending and receiving code is here) http://mpi.deino.net/mpi_functions/MPI_Iprobe.html (at very bottom).

Here is incorrect code from the link with my comments, which part is for sender and which is for receiver side:

#include "mpi.h"
#include <stdio.h>

int main( int argc, char * argv[] )
{
    int rank;
    int sendMsg = 123;
    int recvMsg = 0;
     int flag = 0;
    int count;
     MPI_Status status;
     MPI_Request request;
    int errs = 0;

     MPI_Init( 0, 0 );

     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
     if(rank == 0)  /* There is something incorrect with ranks in this code, please correct */
     {
         MPI_Isend( &sendMsg, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &request );  //sender

        while(!flag)
         {
             MPI_Iprobe( 0, 0, MPI_COMM_WORLD, &flag, &status ); // receiver
         }
         MPI_Get_count( &status, MPI_INT, &count ); // receiver
        if(count != 1)
         {
             errs++;
         }
         MPI_Recv( &recvMsg, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status ); // receiver
         if (recvMsg != 123)
         {
             errs++;
         }

         MPI_Wait( &request, &status ); // sender

     }

     MPI_Finalize();
     return errs;
 }

Upvotes: 3

Related Questions