Skip to content
Snippets Groups Projects
Commit 370e4f35 authored by Chao Zhan's avatar Chao Zhan
Browse files

update slides, add non-blocking examples

parent 232c97a1
Branches
No related tags found
No related merge requests found
PROG = nb_point_2_point
OBJECTS = nb_point_2_point.o
CC = mpicc
CFLAGS = -Wall -std=c11
CFLAGS += -I. # add the current directory to the include path
$(PROG): $(OBJECTS) # link the object files into a binary
$(CC) $(CFLAGS) $^ -o $@
.Phone: run
run: $(PROG) # build and run the program
mpirun -np 2 ./$(PROG)
$(OBJECTS): %.o: %.c # compile the source files into object files
$(CC) $(CFLAGS) -c $<
.PHONY: clean
clean: # remove the object files and the binary
rm -f $(OBJECTS) $(PROG)
#include <mpi.h>
#include <stdio.h>
#include <string.h>
static void busy(void) {
int i;
for (i = 0; i < 10000000; i++) {
if (i % 5000000 == 0) {
printf("Busy...\n");
fflush(stdout);
}
}
printf("Busy...\n");
}
int main(int argc, char **argv) {
char message[32];
MPI_Status status;
MPI_Request request;
MPI_Init(&argc, &argv);
// Get the number of processes
int num_processes;
MPI_Comm_size(MPI_COMM_WORLD, &num_processes);
// Get the rank of the process
int rank;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// Get the name of the processor
char processor_name[MPI_MAX_PROCESSOR_NAME];
int name_len;
MPI_Get_processor_name(processor_name, &name_len);
// forcing the program to run with exactly two processes
if (num_processes != 2) {
fprintf(stderr, "Must use exactly two processes for this program\n");
MPI_Abort(MPI_COMM_WORLD, 1);
} else {
if (rank == 0) {
strncpy(message, "This is not a message!", 32);
MPI_Isend(message, 32, MPI_CHAR, 1, 0, MPI_COMM_WORLD, &request);
busy();
MPI_Wait(&request, &status);
printf("[%s] Message sent: %s\n", processor_name, message);
} else {
MPI_Irecv(message, 32, MPI_CHAR, 0, 0, MPI_COMM_WORLD, &request);
busy();
MPI_Wait(&request, &status);
printf("[%s] Message received: %s\n", processor_name, message);
}
}
// Finalize the MPI environment. No more MPI calls can be made after this
MPI_Finalize();
}
slides/images/deadlock-prevention.png

46.6 KiB

slides/images/non-blocking-detailed.png

77.8 KiB

slides/images/non-blocking.png

83.9 KiB

...@@ -489,3 +489,114 @@ title: Message Ordering ...@@ -489,3 +489,114 @@ title: Message Ordering
- messages arriving from different senders - messages arriving from different senders
See live demo. See live demo.
---
title: Non-Blocking Calls
---
### Non-Blocking Calls
**Non-blocking MPI calls return immediately while the communication operation continues asynchronously in the background**
Each non-blocking operation is represented by a **request**:
- In C: **MPI_Request**
Non-blocking operations are progressed by certain MPI calls but most notably by the **test** and **wait** MPI calls.
Blocking MPI calls = non-blocking calls + immediate waiting
**Benifits?**
<v-click>
<span class="text-rose-500 font-bold">Overlay communications, prevent deadlocks</span>
</v-click>
---
title: Non-Blocking Calls 2
---
## Related Operations
Non-blocking send and receive:
```c
MPI_Isend (void *data, int count, MPI_Datatype dataType, int dest, int tag,
MPI_Comm comm, MPI_Request *request)
MPI_Irecv (void *data, int count, MPI_Datatype dataType, int source, int tag,
MPI_Comm comm, MPI_Request *request)
```
Blocking wait for completion:
```c
MPI_Wait (MPI_Request *request, MPI_Status *status)
```
The request is passed by reference, so that the wait routine can free it:
- The wait call deallocates the request object, **and**
- sets the value of the variable to **MPI_REQUEST_NULL**
---
title: Non-Blocking Calls 3
layout: two-cols
---
**Equivalent to blocking calls**:
<div class="container flex justify-center mt-5 mr-5">
<img src="/images/non-blocking.png" class="block w-lg"/>
</div>
::right::
**Other work can be done in between**:
<div class="container flex justify-center mt-5 ml-5">
<img src="/images/non-blocking-detailed.png" class="block w-lg"/>
</div>
---
title: Deadlock Prevention
---
## Deadlock Prevention
**Non-blocking operations can be used to prevent deadlocks in symmetric code:**
<div class="container flex justify-center mt-5">
<img src="/images/deadlock-prevention.png" class="block w-lg"/>
</div>
<span class="text-rose-500 font-bold">That is how MPI_Sendrecv is usually implemented.</span>
---
title: Non-Blocking Request Testing
---
Using the following function to test if a given operation has completed:
```c
MPI_Test (MPI_Request *request, int *flag, MPI_Status *status)
```
- **flag** will be set to **true** if the operation has completed, otherwise **false**
- **status**: only set if **flag** is **true**
- Can be (and usually is) called repeatedly inside a loop
- When the operations is completed, the **request** is freed and set to **MPI_REQUEST_NULL**
<br/>
### Null Request Object
If **MPI_Request** is Null, both **MPI_Wait** and **MPI_Test** returns immediately.
### Demo
See live demo.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment