From 1328f599540fc4b2232deb812151ffbeba6fb147 Mon Sep 17 00:00:00 2001 From: Pitesse Date: Tue, 3 Dec 2024 18:59:40 +0100 Subject: [PATCH] mpi exercises --- .gitignore | 5 +- NSDS/MPI/NSDS_MPI_tutorial/src/average.c | 67 ++++++++++++---- .../NSDS_MPI_tutorial/src/avoiding_deadlock.c | 29 +++++++ NSDS/MPI/NSDS_MPI_tutorial/src/filter.c | 77 +++++++++++++++---- NSDS/MPI/NSDS_MPI_tutorial/src/hello_world.c | 8 +- NSDS/MPI/NSDS_MPI_tutorial/src/ping_pong.c | 30 +++++++- NSDS/MPI/NSDS_MPI_tutorial/src/probe.c | 10 +++ NSDS/MPI/NSDS_MPI_tutorial/src/ring.c | 24 ++++-- 8 files changed, 209 insertions(+), 41 deletions(-) create mode 100644 NSDS/MPI/NSDS_MPI_tutorial/src/avoiding_deadlock.c diff --git a/.gitignore b/.gitignore index 593e90c..0ee33cf 100644 --- a/.gitignore +++ b/.gitignore @@ -416,4 +416,7 @@ notes.txt package-lock.json package.json -.DS_Store \ No newline at end of file +.DS_Store + +NSDS/MPI/NSDS_MPI_tutorial/src/* +!NSDS/MPI/NSDS_MPI_tutorial/src/*.c \ No newline at end of file diff --git a/NSDS/MPI/NSDS_MPI_tutorial/src/average.c b/NSDS/MPI/NSDS_MPI_tutorial/src/average.c index 85fc94f..d663832 100644 --- a/NSDS/MPI/NSDS_MPI_tutorial/src/average.c +++ b/NSDS/MPI/NSDS_MPI_tutorial/src/average.c @@ -4,36 +4,44 @@ #include // Creates an array of random numbers -int *create_random_array(int num_elements, int max_value) { - int *arr = (int *) malloc(sizeof(int)*num_elements); - for (int i=0; i 1) { + if (argc > 1) + { num_elements_per_proc = atoi(argv[1]); } @@ -42,18 +50,45 @@ int main(int argc, char** argv) { MPI_Init(NULL, NULL); - int my_rank, world_size; + int my_rank, world_size; MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); MPI_Comm_size(MPI_COMM_WORLD, &world_size); // Process 0 creates the array int *global_arr = NULL; - if (my_rank == 0) { + if (my_rank == 0) + { global_arr = create_random_array(num_elements_per_proc * world_size, 100); } - // TODO - + // scatter the array + int *local_arr = (int *)malloc(sizeof(int) * num_elements_per_proc); + MPI_Scatter(global_arr, num_elements_per_proc, MPI_INT, local_arr, num_elements_per_proc, MPI_INT, 0, MPI_COMM_WORLD); + + // compute the average + float local_avg = compute_average(local_arr, num_elements_per_proc); + + printf("Process %d has the average: %f\n", my_rank, local_avg); + + // gather all partial averages + float *partial_avgs = NULL; + if (my_rank == 0) + { + partial_avgs = (float *)malloc(sizeof(float) * world_size); + } + MPI_Gather(&local_avg, 1, MPI_FLOAT, partial_avgs, 1, MPI_FLOAT, 0, MPI_COMM_WORLD); + + // p0 computes the final average + if (my_rank == 0) + { + float final_avg = compute_final_average(partial_avgs, world_size); + printf("Final average: %f\n", final_avg); + free(partial_avgs); + free(global_arr); + } + + free(local_arr); + MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); } diff --git a/NSDS/MPI/NSDS_MPI_tutorial/src/avoiding_deadlock.c b/NSDS/MPI/NSDS_MPI_tutorial/src/avoiding_deadlock.c new file mode 100644 index 0000000..c1c06c8 --- /dev/null +++ b/NSDS/MPI/NSDS_MPI_tutorial/src/avoiding_deadlock.c @@ -0,0 +1,29 @@ +#include +#include + +// Run with two processes. +// Process 0 sends an integer to process 1 and vice-versa. +// Try to run the system: what goes wrong? + +// mpicc deadlock.c -o deadlock +// mpirun -np 2 deadlock + +int main(int argc, char **argv) +{ + MPI_Init(NULL, NULL); + + int my_rank; + MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); + int other_rank = 1 - my_rank; + + int msg_to_send = 1; + int msg_to_recv; + + // send and receive messages in a non-blocking way to avoid deadlock + MPI_Isend(&msg_to_send, 1, MPI_INT, other_rank, 0, MPI_COMM_WORLD, MPI_REQUEST_NULL); + MPI_Irecv(&msg_to_recv, 1, MPI_INT, other_rank, MPI_ANY_TAG, MPI_COMM_WORLD, MPI_REQUEST_NULL); + + printf("Rank %d received message %d from rank %d\n", my_rank, msg_to_recv, other_rank); + + MPI_Finalize(); +} \ No newline at end of file diff --git a/NSDS/MPI/NSDS_MPI_tutorial/src/filter.c b/NSDS/MPI/NSDS_MPI_tutorial/src/filter.c index c6040e5..eb8d128 100644 --- a/NSDS/MPI/NSDS_MPI_tutorial/src/filter.c +++ b/NSDS/MPI/NSDS_MPI_tutorial/src/filter.c @@ -4,46 +4,97 @@ #include // Creates an array of random numbers. -int *create_random_array(int num_elements, int max_value) { - int *arr = (int *) malloc(sizeof(int)*num_elements); - for (int i=0; i 1) { + if (argc > 1) + { num_elements_per_proc = atoi(argv[1]); } - // Init random number generator - srand(time(NULL)); - MPI_Init(NULL, NULL); - int my_rank, world_size; + int my_rank, world_size; MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); MPI_Comm_size(MPI_COMM_WORLD, &world_size); + // Seed the random number generator with a different value for each process + srand(time(NULL) + my_rank); + // Process 0 selects the num int num; - if (my_rank == 0) { + if (my_rank == 0) + { num = num_to_filter_by; } - // TODO - + int *arr = create_random_array(num_elements_per_proc, max_val); + + MPI_Bcast(&num, 1, MPI_INT, 0, MPI_COMM_WORLD); + + filter_array_by_multiples_of_n(arr, num_elements_per_proc, num); + + MPI_Send(arr, num_elements_per_proc, MPI_INT, 0, 0, MPI_COMM_WORLD); + + if (my_rank == 0) + { + int *filtered_arrs = (int *)malloc(sizeof(int) * num_elements_per_proc * world_size); + for (int i = 0; i < world_size; i++) + { + MPI_Recv(filtered_arrs + i * num_elements_per_proc, num_elements_per_proc, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + } + + for (int i = 0; i < world_size; i++) + { + printf("Filtered array from process %d:\n", i); + for (int j = 0; j < num_elements_per_proc; j++) + { + if(filtered_arrs[i * num_elements_per_proc + j] > 0) { + printf("%d ", filtered_arrs[i * num_elements_per_proc + j]); + } + } + printf("\n"); + } + + free(filtered_arrs); + } + + free(arr); + MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); -} + return 0; +} \ No newline at end of file diff --git a/NSDS/MPI/NSDS_MPI_tutorial/src/hello_world.c b/NSDS/MPI/NSDS_MPI_tutorial/src/hello_world.c index e7b93f1..516f83e 100644 --- a/NSDS/MPI/NSDS_MPI_tutorial/src/hello_world.c +++ b/NSDS/MPI/NSDS_MPI_tutorial/src/hello_world.c @@ -1,7 +1,12 @@ #include #include -int main(int argc, char** argv) { +/* +mpicc hello_world.c -o hello +mpirun hello +*/ + +int main(int argc, char *argv[]) { // Init the MPI environment MPI_Init(NULL, NULL); @@ -13,6 +18,7 @@ int main(int argc, char** argv) { int world_rank; MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); + // Get the name of the processor char processor_name[MPI_MAX_PROCESSOR_NAME]; int name_len; diff --git a/NSDS/MPI/NSDS_MPI_tutorial/src/ping_pong.c b/NSDS/MPI/NSDS_MPI_tutorial/src/ping_pong.c index 0a2cdee..42e79c2 100644 --- a/NSDS/MPI/NSDS_MPI_tutorial/src/ping_pong.c +++ b/NSDS/MPI/NSDS_MPI_tutorial/src/ping_pong.c @@ -4,17 +4,39 @@ // Simple ping pong program to exemplify MPI_Send and MPI_Recs // Assume only two processes -int main(int argc, char** argv) { +int main(int argc, char **argv) +{ const int tot_msgs = 100; - + MPI_Init(NULL, NULL); int my_rank; MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); + int other_rank = 1 - my_rank; int num_msgs = 0; - // TODO - + if (my_rank == 0) + { + MPI_Ssend(&num_msgs, 1, MPI_INT, other_rank, 0, MPI_COMM_WORLD); + printf("Rank %d sent message %d to rank %d\n", my_rank, num_msgs, other_rank); + } + + while (num_msgs < tot_msgs) + { + MPI_Recv(&num_msgs, 1, MPI_INT, other_rank, MPI_ANY_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + printf("Rank %d received message %d from rank %d\n", my_rank, num_msgs, other_rank); + num_msgs++; + if (num_msgs <= tot_msgs) + { + MPI_Ssend(&num_msgs, 1, MPI_INT, other_rank, 0, MPI_COMM_WORLD); + printf("Rank %d sent message %d to rank %d\n", my_rank, num_msgs, other_rank); + } + else + { + break; + } + } + MPI_Finalize(); } diff --git a/NSDS/MPI/NSDS_MPI_tutorial/src/probe.c b/NSDS/MPI/NSDS_MPI_tutorial/src/probe.c index 6551c11..95c7764 100644 --- a/NSDS/MPI/NSDS_MPI_tutorial/src/probe.c +++ b/NSDS/MPI/NSDS_MPI_tutorial/src/probe.c @@ -24,6 +24,16 @@ int main(int argc, char** argv) { // Receiver else { // TODO: check the message size and receive + MPI_Status status; + MPI_Probe(other_rank, 0, MPI_COMM_WORLD, &status); + int num_msgs; + MPI_Get_count(&status, MPI_INT, &num_msgs); + int *msgs = (int *) malloc(sizeof(int) * num_msgs); + MPI_Recv(msgs, num_msgs, MPI_INT, other_rank, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + for (int i=0; i