Bureaucrats, cc_docs_admin, cc_staff
2,879
edits
(→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 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 | 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 | 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 | 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. | ||
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: | ||
|} | |} | ||
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 ~]$ 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 |