0
votes

Essentially what I am looking for here is a simple MPI_SendRecv() routine that allows me to synchronize the same buffer by specifying a source and a destination processor.

In my mind the function call for my Ideal_MPI_SendRecv() function would look precisely like MPI_Bcast() but would contain a destination process instead of a Communicator.

It might be called as follows:

Ideal_MPI_SendRecv(&somebuffer, bufferlength, datatype, source_proc, destination_proc);

If not, is there any reason? It seems like this method would be the perfect method to synchronize a variable's values between two processes.

2

2 Answers

2
votes

No, there is no such call in MPI since it is trivial to implement it using point-to-point communication. Of course you could write one, for example (with some rudimentary support for error handling):

// Just a random tag that is unlikely to be used by the rest of the program
#define TAG_IDEAL_SNDRCV     11223

int Ideal_MPI_SendRecv(void *buf, int count, MPI_Datatype datatype,
                       int source, int dest, MPI_Comm comm)
{
   int rank;
   int err;

   if (source == dest)
      return MPI_SUCCESS;
   err = MPI_Comm_rank(comm, &rank);
   if (err != MPI_SUCCESS)
      return err;
   if (rank == source)
      err = MPI_Send(buf, count, datatype, dest, TAG_IDEAL_SNDRCV, comm);
   else if (rank == dest)
      err = MPI_Recv(buf, count, datatype, source, TAG_IDEAL_SNDRCV, comm,
                     MPI_STATUS_IGNORE);
   return err;
}

// Example: transfer 'int buf[10]' from rank 0 to rank 2
Ideal_MPI_SendRecv(buf, 10, MPI_INT, 0, 2, MPI_COMM_WORLD);

You could also add another output argument of type MPI_Status * and store the status of MPI_Recv there. It could be useful if both processes have different buffer sizes.

Another option would be, if you have to do that many times within a fixed set of ranks, e.g. always from rank 0 to rank 2, you could simply create a new communicator and broadcast inside it:

int rank;
MPI_Comm buddycomm;

MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_split(MPI_COMM_WORLD, (!rank || rank == 2) ? 0 : MPI_UNDEFINED, rank,
               &buddycomm);

// Transfer 'int buf[10]' from rank 0 to rank 2
MPI_Bcast(buf, 10, MPI_INT, 0, buddycomm);

This, of course, is an overkill since the broadcast is more expensive than the simple combination of MPI_Send and MPI_Recv.

1
votes

Perhaps you want to call MPI_Send on one process (the source process, with the values you want) and MPI_Recv on another process (the one which doesn't initially have the values you want)?

If not, could you clarify how what you're trying to accomplish differs from a simple point-to-point message?