Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: various typos and code fixes for intro to mpi #216

Merged
merged 5 commits into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ int main(int argc, char **argv) {

### Scatter

One way to parallelise processing amount of data is to have ranks process a subset of the data.
One way to parallelise processing an amount of data is to have ranks process a subset of the data.
One method for distributing the data to each rank is to have a root rank which prepares the data, and then send the data to every rank.
The communication could be done *manually* using point-to-point communication, but it's easier, and faster, to use a single collective communication.
We can use `MPI_Scatter()` to split the data into *equal* sized chunks and communicate a different chunk to each rank, as shown in the diagram below.
Expand Down Expand Up @@ -476,7 +476,7 @@ Not all collective operations support in-place operations, and the usage of `MPI

:::::challenge{id=reductions, title="Reductions"}
The following program creates an array called `vector` that contains a list of `n_numbers` on each rank.
The first rank contains the numbers from > 1 to n_numbers, the second rank from n_numbers to 2*n_numbers2 and so on.
The first rank contains the numbers from 0 to n_numbers, the second rank from n_numbers to 2*n_numbers and so on.
It then calls the `find_max` and `find_sum` functions that should calculate the sum and maximum of the vector.

These functions are not implemented in parallel and only return the sum and the maximum of the local vectors.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ int main(int argc, char **argv)

if (num_ranks < 2) {
printf("This example requires at least two ranks\n");
MPI_Abort(MPI_COMM_WORLD, 1);
return MPI_Finalize();
}

char send_message[MESSAGE_SIZE];
Expand Down
17 changes: 7 additions & 10 deletions high_performance_computing/hpc_mpi/08_porting_serial_to_mpi.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ And finally, the state of the stick is set to the newly calculated values, and `

```c
// Overwrite u with the new field
for (int i = 1 ;i <= points; ++i) {
for (int i = 1; i <= points; i++) {
u[i] = unew[i];
}

Expand Down Expand Up @@ -398,10 +398,9 @@ Such an order might look like this (highlighting the odd ranks - only one in thi

![Communication strategy - odd ranks send to potential neighbours first, then receive from them](fig/poisson_comm_strategy_1.png)

So following the `MPI_Allreduce()` we've just added, let's deal with odd ranks first (again, put the declarations at the top of the function):
So, following the code that overwrites `u` with the new field, let's deal with odd ranks first (again, put the declarations at the top of the function):

```c
float sendbuf, recvbuf;
MPI_Status mpi_status;

// The u field has been changed, communicate it to neighbours
Expand All @@ -410,12 +409,10 @@ So following the `MPI_Allreduce()` we've just added, let's deal with odd ranks f
if ((rank % 2) == 1) {
// Ranks with odd number send first

// Send data down from rank to rank - 1
sendbuf = unew[1];
MPI_Send(&sendbuf, 1, MPI_FLOAT, rank - 1, 1, MPI_COMM_WORLD);
// Receive data from rank - 1
MPI_Recv(&recvbuf, 1, MPI_FLOAT, rank - 1, 2, MPI_COMM_WORLD, &mpi_status);
u[0] = recvbuf;
// Send data down from rank to rank-1
MPI_Send(&u[1], 1, MPI_FLOAT, rank-1, 1, MPI_COMM_WORLD);
// Receive dat from rank-1
MPI_Recv(&u[0], 1, MPI_FLOAT, rank-1, 2, MPI_COMM_WORLD, &mpi_status);

if (rank != (n_ranks - 1)) {
// Send data up to rank + 1 (if I'm not the last rank)
Expand All @@ -431,7 +428,7 @@ We first send our newly computed leftmost value (at position `1` in our array) t

Then, if the rank following us exists, we do the same, but this time we send the rightmost value at the end of our stick section, and receive the corresponding value from that rank.

These exchanges mean that - as an even rank - we now have effectively exchanged the states of the start and end of our slices with our respective neighbours.
These exchanges mean that - as an odd rank - we now have effectively exchanged the states of the start and end of our slices with our respective neighbours.

And now we need to do the same for those neighbours (the even ranks), mirroring the same communication pattern but in the opposite order of receive/send. From the perspective of evens, it should look like the following (highlighting the two even ranks):

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ To communicate the halos, we need to:
3. Using the derived types and neighbouring ranks, communicate the top row of the sub-domain to the bottom halo row of the neighbouring top domain.
We also need to repeat the same process for the bottom row to the neighbouring sub-domain below and so on for the left and right columns of halo data.

To re-build the sub-domains into one domain, we can do the reverse of the hidden code exert of the function `scatter_sub_arrays_to_other ranks`.
To re-build the sub-domains into one domain, we can do the reverse of the the function `scatter_sub_arrays_to_other_ranks` shown [above](#extra-scattering-the-image-to-other-ranks)
Instead of the root rank sending data, it instead receives data from the other ranks using the same `sub_array_t` derived type.
::::
:::::