Do I need to have the appropriate MPI :: Irecv for MPI :: Isend?

Apparently a stupid question, but I can't find a definitive answer anyway.

Key questions: do I need MPI :: Irecv for MPI :: Isend?

That is, despite the fact that sending a message is not blocked, if I wait for the completion of sending before reusing the send buffers, do I need to use non-blocking reception and wait for the received buffers to be received?

I want to say that I want to use non-blocking messages to “do other things” while the message is being sent, but the recipient process will use the buffers immediately, so I want them to lock until the buffer is actually received.

It seems that I should receive messages from MPI :: Recv, even if they were sent from MPI :: Isend, but I wonder if I am missing something?

A bit of simple pseudo code

if( rank == 0 ){ int r; for ( int i = 0; i < n; i++ ){ // DO SOME STUFF HERE... request.Wait(status); request2.Wait(status); request3.Wait(status); r = i; memcpy( key, fromKey(i), ...); memcpy( trace, fromTrace(i), ...); request = MPI::COMM_WORLD.Isend( &r, 1, MPI::INT, node, tag ); request2 = MPI::COMM_WORLD.Isend( key, 10, MPI::INT, node, tag ); request3 = MPI::COMM_WORLD.Isend( trace, nBytesTotal, MPI::BYTE, node, tag ); // DO SOME MORE STUFF HERE. } r = -1; request = MPI::COMM_WORLD.Isend( &r, 1, MPI::INT, node, tag ); // Carry on ... } else { int r = -1; MPI::COMM_WORLD.Recv( &r, 1, MPI::INT, 0, tag, status ); while( r >= 0 ){ MPI::COMM_WORLD.Recv( &key, 10, MPI::INT, 0, tag, status ); memcpy( saveKey, key, ...); MPI::COMM_WORLD.Recv( &trace, nBytesTotal, MPI::BYTE, 0, tag, status ); memcpy( saveTrace, trace, ...); MPI::COMM_WORLD.Recv( &r, 1, MPI::INT, 0, tag, status ); } 
+6
source share
3 answers

No, you can freely mix blocking and non-blocking MPI operations at both ends of the connection. The lock is when the MPI call returns control to your code, and not to the contents of the message being sent.

Each MPI message carries an "envelope" containing its source, destination address, tag, and communicator. To receive the message successfully, your receive operation must < match the envelope . The envelope does not indicate in any way how the message was sent - whether it was using a lock, whether it was using a non-blocking operation, whether it was synchronous sending ( MPI_Ssend ) or buffered ( MPI_Bsend ). The only exception is the so-called “mode ready” initiated by MPI_Rsend() or MPI_Irsend() , which requires that the corresponding receive operation has already been sent or the message will not be delivered.

That's why the term “consistent receive operation” is used throughout the MPI standard, rather than something like “corresponding receive function”.

+15
source

Yes, that's great. There is no requirement that the send / recv types (or whatever you want to name) match.

0
source

This is independent of what send / recv command you use; but implementation is important. You should know about blocking points in the code. For example, when using blocking communications you should take care of calls and tricks, for example look at this code

  if(rank==0) { MPI_Send(x to process 1) MPI_Recv(y from process 1) } if(rank==1) { MPI_Send(y to process 0); MPI_Recv(x from process 0); } 

what happens in this case? process 0 sends x for processing 1 and blocks until process 1 receives x, process 0 sends y to process 0 and blocks until process 0 receives y, but process 0 is blocked, so process 1 blocks for infinity until you kill 2 processes

0
source

Source: https://habr.com/ru/post/916108/


All Articles