MPI: Difference between revisions

Jump to navigation Jump to search
315 bytes removed ,  8 years ago
→‎Safe MPI: copyediting and simplification
(→‎Communication: more copyediting)
(→‎Safe MPI: copyediting and simplification)
Line 370: Line 370:
The MPI standard defines <tt>MPI_Send</tt> and <tt>MPI_Recv</tt> to be '''blocking calls'''. The correct way to interpret this is that <tt>MPI_Send</tt> will not return until it is safe for the calling module to modify the contents of the provided message buffer.  Similarly, <tt>MPI_Recv</tt> will not return until the entire contents of the message are available in the provided message buffer.
The MPI standard defines <tt>MPI_Send</tt> and <tt>MPI_Recv</tt> to be '''blocking calls'''. The correct way to interpret this is that <tt>MPI_Send</tt> will not return until it is safe for the calling module to modify the contents of the provided message buffer.  Similarly, <tt>MPI_Recv</tt> will not return until the entire contents of the message are available in the provided message buffer.


It should be obvious that the availability of buffering in the MPI library is irrelevant to receive operations. It is meaningless to speak of buffering something that hasn't yet been received. As such we assume that <tt>MPI_Recv</tt> will always block until the message is fully received. <tt>MPI_Send</tt> on the other hand need not block if there is buffering present in the library. Once the message is copied out of the buffer for delivery, it is safe for the user to modify the buffer, so the call can return. This is why our parallel "Hello, world!" program doesn't deadlock as we have implemented it, even though all processes call <tt>MPI_Send</tt> first. This relies on there being buffering in the MPI library on our systems, which is not required by the MPI standard, and thus we refer to such a program as '''''unsafe''''' MPI.
It should be obvious that the availability of buffering in the MPI library is irrelevant to receive operations. As soon as the data is received it will be made available and <tt>MPI_Recv</tt> will return; until then it will be blocked and there is nothing to buffer. <tt>MPI_Send</tt> on the other hand need not block if there is buffering present in the library. Once the message is copied out of the buffer for delivery, it is safe for the user to modify the original data, so the call can return. This is why our parallel "Hello, world!" program doesn't deadlock as we have implemented it, even though all processes call <tt>MPI_Send</tt> first. This relies on there being buffering in the MPI library on our systems. Since this is not required by the MPI standard, we refer to such a program as '''''unsafe''''' MPI.


A '''''safe''''' MPI program is one that does not rely on a buffered underlying implementation in order to function correctly. The following pseudo-code fragments illustrate this concept clearly:
A '''''safe''''' MPI program is one that does not rely on a buffered implementation in order to function correctly. The following pseudo-code fragments illustrate this concept:


==== Deadlock ====
==== Deadlock ====
Line 408: Line 408:
</source>
</source>


This is essentially what our parallel "Hello, world!" program was doing, and in general this ''may'' work if buffering is provided by the library. If the library is unbuffered, or even if messages are simply sufficiently large to fill the buffer, this code '''will''' block on the sends, and deadlock.
This is essentially what our parallel "Hello, world!" program was doing, and it ''may'' work if buffering is provided by the library. If the library is unbuffered, or if messages are simply large enough to fill the buffer, this code will block on the sends, and deadlock.


==== Safe ====
==== Safe ====
Line 426: Line 426:
</source>
</source>


Even in the absence of buffering, the send here is paired with a corresponding receive between processes. While a process may block for a short time until the corresponding call is made, it is not possible for deadlock to occur in this code regardless of buffering.
Even in the absence of buffering, the send here is paired with a corresponding receive between processes. While a process may block for a time until the corresponding call is made, it cannot deadlock.


The last thing we will consider then is how to recast our "Hello, World!" program so that it is ''safe''. A common solution to this kind of data-exchange issue, where all processes are exchanging data with a subset of other processes, is to adopt an odd-even pairing and perform the communication in two steps. In this case communication is a rotation of data one rank to the right, so we end up with a safe program if all even ranked processes execute a send followed by a receive, while all odd ranked processes execute a receive followed by a send. The reader can verify that the sends and receives are properly paired avoiding any possibility of deadlock.
How do we rewrite our "Hello, World!" program to make it safe? A common solution to this kind of problem is to adopt an odd-even pairing and perform the communication in two steps. In this case communication is a rotation of data one rank to the right, so we end up with a safe program if all even ranked processes execute a send followed by a receive, while all odd ranked processes execute a receive followed by a send. The reader can verify that the sends and receives are properly paired avoiding any possibility of deadlock.


{| border="0" cellpadding="5" cellspacing="0" align="center"
{| border="0" cellpadding="5" cellspacing="0" align="center"
Line 521: Line 521:
|}
|}


In the interest of completeness, it should be noted that in this implementation, there is the possibility of a blocked <tt>MPI_Send</tt> where the number of processors is odd---one processor will be sending while another is trying to send to it. Verify for yourself that there can only be one processor affected in this way. This is still safe however since the receiving process was involved in a send that was correctly paired with a receive, so the blocked send will complete as soon as the <tt>MPI_Recv</tt> call is executed on the receiving process.
Is there still a problem here if the number of processors is odd? It might seem so at first, since process 0 (which is even) will be sending while process N-1 (also even) is trying to send to 0. But process 0 is originating a send that is correctly paired with a receive at process 1. Since process 1 (odd) begins with a receive, that transaction is guaranteed to complete. When it is complete, process 0 will proceed to receive the message from process N-1. There may be a (very small!) delay, but there is no chance of a deadlock.


[orc-login2 ~]$ vi phello3.c
  [orc-login2 ~]$ mpicc -Wall phello3.c -o phello3
  [orc-login2 ~]$ mpicc -Wall phello3.c -o phello3
  [orc-login2 ~]$ mpirun -np 16 ./phello3
  [orc-login2 ~]$ mpirun -np 16 ./phello3
Bureaucrats, cc_docs_admin, cc_staff
2,879

edits

Navigation menu