# PHAS0100 - week 10 (25th March 2022) :::info ## :tada: Welcome to the 10th and final live-class! ### Today Today we will - Recap shared memory parallelism - Intro to the Message Parsing Interface (MPI) - Work through OpenMPI examples: - Hello world-type with/without catch2 - Point to point communications - Collective operations: scatter and reduce - Finish with a summary of the course ::: ### Timetable for today | Start | End | Topic | Room | | -------- | -------- | -------- | ----- | | 14:05 | 14:25 | Intro shared memory + MPI | Main | | 14:25 | 14:50 | [Install OpenMPI + hello/helloCatch](#Breakout-session-1) | Breakouts | |14:50 | 15:00 | Break | ---| |15:00 | 15:20 | Collective communications | Main | | 15:20 | 15:50 | [Scatter and reduce examples](#Breakout-session-2) | Breakouts | |15:50 | 16:00 | Break | --- | |16:00 | 16:20 | Point-to-point communications | Main | | 16:20 | 16:45 | [Ring pattern and SendRecv](#Breakout-session-3) | Breakouts | |16:45 | 17:00 | Closeout and questions | Main | # Breakout session 1 ## Class Exercise 1 **OpenMPI libraries and hello.cpp** 1. First clone the repository for today's class ``` git clone https://github.com/jeydobson/phas0100_week10_mpi.git ``` 2. Open the folder in VS Code and then `Reopen in Container` to build the updated Dockerfile image with OpenMPI libraries :::spoiler alternative If you prefer to install in a running container ``` shell sudo apt-get update sudo apt-get install openmpi-bin libopenmpi-dev ``` ::: 3. Check that the OpenMPI libraries installed ``` shell mpiexec --version mpicxx --version ``` :::warning As we will run cmake steps manually from the terminal it is useful to disable VS Code's automatic re-run of cmake every time a CMakeLists.txt file is saved: open the VS Code extensions tab -> `CMake Tools` extension settings -> Workspace -> uncheck the `Configure on Edit` setting. ::: 4. Add the relevant CMake commands to `phas0100_week10_mpi/hello/CMakeLists.txt` to compile `hello.cpp` Note: in order to get onto latter parts of this question, take a look at the hints below if this takes more than a few minutes :::spoiler hints Use `add_executable` and `target_link_libraries` The `MPI_CXX_LIBRARIES` is set by find_package and points to the MPI libraries. If that doesn't help see `hello/solution` ::: 5. Compile as usual ``` cd phas0100_week10_mpi mkdir build cd build cmake .. make ``` 6. Now from within `build` try running: ``` mpiexec ./hello/hello mpiexec -n <num_processors> ./hello/hello mpiexec -n <num_processors> --oversubscribe ./hello/hello ``` * Try out a few different values for ``<numprocessors>`` 1, 2, 10. The `--oversubscribe` option is necessary if `<numprocessors>` is greater than those available on your system. * Take a look at `hello.cpp`and discuss how running with different `<num_processors>` affects the output? Make sure you understand `MPI_Comm_rank` and `MPI_Comm_size` * What happens if you run the executable without `mpiexec`? 7. If you have time, look at the https://www.open-mpi.org/doc/v3.1/ docs and see if the documentation for `MPI_Comm_rank` and `MPI_Comm_size` makes sense. Try to get the communicator name with `MPI_Comm_get_name`? ## Class Exercise 2 **helloCatch.cpp** 1. Add relevant CMake commands to `phas0100_week10_mpi/hello/CMakeLists.txt` to compile `helloCatch.cpp` 2. As with `hello.cpp` run cmake, make 3. Try running with `mpiexec` with various numbers of :::spoiler Optional if time left over 5. Take a look at the https://www.open-mpi.org/doc/v3.1/ docs and see if the documentation for `MPI_Comm_rank` and `MPI_Comm_size` makes sense. Can you use `MPI_Comm_get_name` to get the name of the communicator? ::: # Breakout session 2 ## Class Exercise 3 **Scatter a message with MPI_Scatter** 1. Uncomment `add_subdirectory(collective)` in the top-level `phas0100_week10_mpi/CMakeLists.txt` file so that cmake tries to compile and add relevant commands to `phas0100_week10_mpi/collective/CMakeLists.txt` to compile `scatter.cpp` 2. Use the `MPI_Scatter` method to split `"This message is going to come out in separate channels"` evenly based on number of proccess and send each chunk to a process ## Class Exercise 4 **Sum resuts from different processes with MPI_Reduce** In this example the aim is to calculate pi using the Gregory and Leibniz formula: ``` pi/4 = 1 - 1/3 + 1/5 - 1/7 + ... ``` but we will split the series into chunks and process each chunk on a separate process and then use MPI_Reduce to sum them all and pass the result to the root process (rank 0). 1. Add relevant commands to `phas0100_week10_mpi/collective/CMakeLists.txt` to compile `reduce.cpp` 2. Use the MPI_Reduce method to sum the results from each process to calculate pi/4. A list of the pre-defined operators can be found further down the page here https://www.open-mpi.org/doc/v3.1/man3/MPI_Reduce.3.php # Breakout session 3 ## Class Exercise 5 **ring with blocking synchronous MPI_SSend** 0. Throughtout, use https://www.open-mpi.org/doc/v3.1/ to look up MPI method documentation 1. Uncomment `add_subdirectory(point2point)` in the top-level `phas0100_week10_mpi/CMakeLists.txt` file so that cmake tries to compile and add relevant commands to `phas0100_week10_mpi/point2point/CMakeLists.txt` to compile `ring.cpp` 2. For even ranked processes: implement an `MPI_Ssend` to send `message` from the current process to the one on its left 3. For even processes: implement an `MPI_Recv` to recieve the `message` from the process on the right 4. Then for odd processes: first call `MPI_Recv` 5. And then `MPI_Ssend` 6. Check the final REQUIRE passes. What happends if you reverse the order of 4 and 5? :::info You can use the `-c` options to tell catch2 to only run tests for a specific section like this ``` shell mpiexec --oversubscribe -n 4 point2point/ring -c "Blocking synchronous" ``` ::: ## Class/Homework Exercise 6 **ring with asynchronous MPI_ISend** Now implement using the asynchronous `MPI_ISend` in the `Asynchronous` SECTION. 1. First use `MPI_Isend` to send for all processes. 2. Then use `MPI_Recv` to receive messages for all processes. `MPI_Recv` also acts as a sync barrier. 3. Implement an `MPI_Test` to check the `MPI_Request` handle for`MPI_Isend`. Confirm that it is always set to `true`. ## Class/Homework Exercise 7 **ring with MPISendRecv** This send-recieve ring pattern is so common there is a dedicated method for it: `MPI_Sendrecv`. 1. Use MPI_Sendrecv to achieve the same as above but now in a single command. Once this is implemented the final REQUIRE check should pass. ## End of module Evaluation feedback Please, fill up [the survey to help us improve](https://moodle.ucl.ac.uk/mod/questionnaire/view.php?id=3352333) our teaching and your learning experience. # Questions Here you can post any question you have while we are going through this document. A summary of the questions and the answers will be posted in moodle after each session. Please, use a new bullet point for each question and sub-bullet points for their answers. For example writing like this: ``` - Example question - [name=student_a] Example answer - [name=TA_1] Example answer ``` produces the following result: - Example question - [name=student_a] Example answer - [name=TA_1] Example answer Write new questions below :point_down: - [] - [name=TA_1] Example answer ###### tags: `phas0100` `teaching` `class`