Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MPI Sendrecv with MPI_ANY_SOURCE

Tags:

c

mpi

Is it possible to do an MPI_Sendrecv exchange where one side does not know the rank of the other? If not, what is the best way to do that (my next guess would just be a pair of sends and recvs)?

For example in C if I want to exchange integers between rank 0 and some other rank would this type of thing work?:

MPI_Status stat;
if(rank){
  int someval = 0;
  MPI_Sendrecv(&someval, 1, MPI_INT, 0, 1, &recvbuf, 1, MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &stat);
}else{
  int someotherval = 1;
  MPI_Sendrecv(&someotherval, 1, MPI_INT, MPI_ANY_SOURCE, someotherval, &recvbuf, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &stat);
}

EDIT: Looks like it is not possible. I whipped up the following as a sort of wrapper to add the functionality that I need.

void slave_sendrecv(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
    int dest, int sendtag, void *recvbuf, int recvcount,
    MPI_Datatype recvtype, int source, int recvtag, MPI_Status *status){

    MPI_Send(sendbuf, sendcount, sendtype, dest, sendtag, MPI_COMM_WORLD);
    MPI_Recv(recvbuf, recvcount, recvtype, source, recvtag, MPI_COMM_WORLD, status);
}

void anon_sendrecv(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
    int sendtag, void *recvbuf, int recvcount,
    MPI_Datatype recvtype, int recvtag, MPI_Status *status){

    int anon_rank;
    MPI_Recv(recvbuf, recvcount, recvtype, MPI_ANY_SOURCE, recvtag, MPI_COMM_WORLD, status);
    anon_rank = status -> MPI_SOURCE;
    MPI_Send(sendbuf, sendcount, sendtype, anon_rank, sendtag, MPI_COMM_WORLD);
}

EDIT 2: Based on Patrick's answer it looks like the slave_sendrecv function above is not needed, you can just use regular MPI_Sendrecv on the end that knows who it's sending to.

like image 645
kag0 Avatar asked Sep 29 '22 08:09

kag0


1 Answers

Short answer: No.

The standard does not allow the use of MPI_ANY_SOURCE as the destination rank dest in any send procedure. This make sense, since you can not send a message without knowing the destination.

The standard however does permit you to pair a MPI_Sendrecv with regular MPI_Send/MPI_Recv:

A message sent by a send-receive operation can be received by a regular receive operation or probed by a probe operation; a send-receive operation can receive a message sent by a regular send operation.

In your case, process 0 will have to first receive, and then answer:

MPI_Status stat;
if(rank){
  int someval = 0;
  MPI_Sendrecv(&someval, 1, MPI_INT, 0, 1, &recvbuf, 1, MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &stat);
}else{
  int someotherval = 1;
  MPI_Recv(&recvbuf, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &stat);
  // answer to process `stat.MPI_SOURCE` using `someotherval` as tag
  MPI_Send(&someotherval, 1, MPI_INT, stat.MPI_SOURCE, someotherval, MPI_COMM_WORLD);
}
like image 114
Patrick Avatar answered Oct 17 '22 19:10

Patrick