mirror of
https://github.com/fverdugo/XM_40017.git
synced 2025-11-08 20:24:25 +01:00
Minor changes in MPI point to point notebook
This commit is contained in:
parent
9ad56cd685
commit
0cee9268b5
@ -528,7 +528,7 @@
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div class=\"alert alert-block alert-info\">\n",
|
||||
"<b>Note:</b> Function `mpiexec` provided by `MPI.jl` is a convenient way of accessing the `mpiexec` program that matches the MPI installation used my Julia.\n",
|
||||
"<b>Note:</b> Function `mpiexec` provided by `MPI.jl` is a convenient way of accessing the `mpiexec` program that matches the MPI installation used by Julia.\n",
|
||||
"</div>"
|
||||
]
|
||||
},
|
||||
@ -974,7 +974,7 @@
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"`MPI_Send` is also often called a blocking send, but this is very misleading. `MPI_Send` might or not wait for a matching `MPI_Recv`. Look into the following example (which in fact is an incorrect MPI program)."
|
||||
"`MPI_Send` is also often called a blocking send, but this is very misleading. `MPI_Send` might or not wait for a matching `MPI_Recv`. Assuming that `MPI_Send` will block waiting for a matching receive is erroneous. I.e., we cannot assume that `MPI_Send` has synchronization side effects with the receiver process. However, assuming that `MPI_Send` will not block is also erroneous. Look into the following example (which in fact is an incorrect MPI program). In contrast, `MPI_Send` guarantees that the send buffer can be reused when function returns (complete operation)."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -1047,7 +1047,7 @@
|
||||
"source": [
|
||||
"## Fixing cyclic dependencies\n",
|
||||
"\n",
|
||||
"Returning to the incorrect program seen before. Remember that on my laptop it worked for `n=1`, but it failed for `n=10000`. For `n=1` the MPI implementation provably decided that the best trade-off was to buffer the small message and return from the `MPI_Send` as soon as possible. For the large message (`n=10000`) it provably decided to wait for a matching receive in ordeer to avoid copying data. In this case, both ranks were blocked on the call to `MPI_Send` and the receives were never posted leading to a dead lock.\n",
|
||||
"Returning to the incorrect program seen before. Remember that on my laptop it worked for `n=1`, but it failed for `n=10000`. For `n=1` the MPI implementation provably decided that the best trade-off was to buffer the small message and return from the `MPI_Send` as soon as possible. For the large message (`n=10000`) it provably decided to wait for a matching receive in order to avoid copying data. In this case, both ranks were blocked on the call to `MPI_Send` and the receives were never posted leading to a dead lock.\n",
|
||||
"\n",
|
||||
"We can fix these cyclic dependences by smartly ordering the sends and the receives:"
|
||||
]
|
||||
@ -1149,10 +1149,11 @@
|
||||
"source": [
|
||||
"### Standard mode\n",
|
||||
"\n",
|
||||
"* Function `MPI_Send` \n",
|
||||
"* Function `MPI_Send`.\n",
|
||||
"* Programmer cannot make any assumptions whether the message is buffered or not. This is up to the system.\n",
|
||||
"* Assuming buffering might lead to incorrect programs (as the example above).\n",
|
||||
"* Assuming that a matching receive started is also incorrect."
|
||||
"* Assuming that `MPI_Send` does not block because it copies the message into a buffer is erroneous (as the example above).\n",
|
||||
"* Assuming that `MPI_Send` will block waiting for a matching receive is also incorrect. \n",
|
||||
"* Assuming that a matching receive started when `MPI_Send`returns is also incorrect (no synchronization guarantee)."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -1160,9 +1161,9 @@
|
||||
"id": "014ef71f",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Buffered\n",
|
||||
"### Buffered mode\n",
|
||||
"\n",
|
||||
"* Function `MPI_Bsend`\n",
|
||||
"* Function `MPI_Bsend`.\n",
|
||||
"* Programmer provides additional internal buffer space with function `MPI_Buffer_attach`.\n",
|
||||
"* `MPI_Bsend` completes when message is copied into a local buffer.\n",
|
||||
"* Erroneous if buffer space is insufficient.\n",
|
||||
@ -1174,12 +1175,12 @@
|
||||
"id": "bf456a3e",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Synchronous\n",
|
||||
"### Synchronous mode\n",
|
||||
"\n",
|
||||
"* Function `MPI_Ssend`\n",
|
||||
"* It waits for a matching receive and it is guaranteed that the receive started.\n",
|
||||
"* No extra data copy\n",
|
||||
"* Easy to get deadlocks\n",
|
||||
"* Function `MPI_Ssend`.\n",
|
||||
"* It waits for a matching receive and it is guaranteed that the receive started (synchronization guarantee).\n",
|
||||
"* No extra data copy.\n",
|
||||
"* Easy to get deadlocks.\n",
|
||||
"* It can be started whether or not a matching receive was posted."
|
||||
]
|
||||
},
|
||||
@ -1188,9 +1189,9 @@
|
||||
"id": "a1bd72c3",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Ready\n",
|
||||
"### Ready mode\n",
|
||||
"\n",
|
||||
"* Function `MPI_Rsend`\n",
|
||||
"* Function `MPI_Rsend`.\n",
|
||||
"* It may be started only if the matching receive is already posted. This allows the underlying implementation to skip some operations, such as a [handshake](https://en.wikipedia.org/wiki/Handshake_(computing)).\n",
|
||||
"* Erroneous if there is no matching receive yet.\n",
|
||||
"* Otherwise, the same as the synchronous `MPI_Ssend`."
|
||||
@ -1242,7 +1243,7 @@
|
||||
"source": [
|
||||
"## Incomplete operations\n",
|
||||
"\n",
|
||||
"Functions `MPI_Isend` and `MPI_Irecv` are *incomplete* operations, hence the `I` in `MPI_Isend` and `MPI_Irecv`. This means that, when these functions return, there is no guarantee that the underlying operation has finished. Function `MPI_Wait` should be used to wait for completion of the send and/or receive.\n",
|
||||
"Functions `MPI_Isend` and `MPI_Irecv` are *incomplete* operations, hence the `I` in `MPI_Isend` and `MPI_Irecv`. This means that, when these functions return, there is no guarantee that the underlying operation has finished. Function `MPI_Wait` should be used to wait for completion of the send and/or receive.\n",
|
||||
"\n",
|
||||
"In particular:\n",
|
||||
"\n",
|
||||
@ -1354,7 +1355,7 @@
|
||||
"\n",
|
||||
"Remember that we used `MPI_Probe` to query for the size of an incoming message. However, if we use `MPI_Probe` we miss the opportunity to do local work before a matching send started, i.e. we cannot do latency hiding.\n",
|
||||
"\n",
|
||||
"This can be fixed using an `MPI_Iprobe`, i.e., an incomplete probe. It allows us to check for incoming messages without blocking.\n",
|
||||
"This can be fixed using an `MPI_Iprobe`, i.e., an incomplete probe (aka a non-blocking probe). It allows us to check for incoming messages without blocking.\n",
|
||||
"\n",
|
||||
"In Julia:\n",
|
||||
"```julia\n",
|
||||
@ -1363,8 +1364,11 @@
|
||||
"\n",
|
||||
"In C:\n",
|
||||
"```C\n",
|
||||
"int MPI_Iprobe(int source, int tag, MPI_Comm comm, int *flag,\n",
|
||||
" MPI_Status *status)\n"
|
||||
"int MPI_Iprobe(int source, int tag, MPI_Comm comm, int *ismsg,\n",
|
||||
" MPI_Status *status)\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"Function `MPI_Iprobe` returns immediately without waiting for a matching send. The value of `ismsg` tells if a send was posted or not. If there was a send, the `status` object can be used to get information about the incoming message as we saw before."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -1464,7 +1468,7 @@
|
||||
"source": [
|
||||
"## Summary\n",
|
||||
"\n",
|
||||
"We have seen different ways of sending and receiving messages with MPI, each one with its pros and cons. You as user should decide which is the best option for a given problem. We also learned how to get information about an incoming messages with `MPI_Status`, `MPI_Probe`, and `MPI_Iprobe`. In addition, we saw how easy is to write incorrect programs if you do not follow the semantics of the MPI operations properly.\n"
|
||||
"We have seen different ways of sending and receiving messages with MPI, each one with its pros and cons. You as user should decide which is the best option for a given problem. We also learned how to get information about an incoming messages with `MPI_Status`, `MPI_Probe`, and `MPI_Iprobe`. In addition, we saw how easy is to write incorrect programs with if you do not follow the semantics of the MPI operations properly.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user