Skip to content

Commit

Permalink
mpi exercises
Browse files Browse the repository at this point in the history
  • Loading branch information
PietroPizzoccheri committed Dec 3, 2024
1 parent 6e7eb23 commit 1328f59
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 41 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -416,4 +416,7 @@ notes.txt
package-lock.json
package.json

.DS_Store
.DS_Store

NSDS/MPI/NSDS_MPI_tutorial/src/*
!NSDS/MPI/NSDS_MPI_tutorial/src/*.c
67 changes: 51 additions & 16 deletions NSDS/MPI/NSDS_MPI_tutorial/src/average.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,44 @@
#include <mpi.h>

// 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<num_elements; i++) {
int *create_random_array(int num_elements, int max_value)
{
int *arr = (int *)malloc(sizeof(int) * num_elements);
for (int i = 0; i < num_elements; i++)
{
arr[i] = (rand() % max_value);
}
return arr;
}

// Computes the average value
float compute_average(int *array, int num_elements) {
float compute_average(int *array, int num_elements)
{
int sum = 0;
for (int i=0; i<num_elements; i++) {
for (int i = 0; i < num_elements; i++)
{
sum += array[i];
}
return ((float) sum) / num_elements;
return ((float)sum) / num_elements;
}

// Computes final average value
float compute_final_average(float *array, int num_elements) {
// Computes final average value from other averages
float compute_final_average(float *array, int num_elements)
{
float sum = 0.0f;
for (int i=0; i<num_elements; i++) {
for (int i = 0; i < num_elements; i++)
{
sum += array[i];
}
return sum/num_elements;
return sum / num_elements;
}

int main(int argc, char** argv) {
int main(int argc, char **argv)
{
// Number of elements for each processor
int num_elements_per_proc = 1000;
if (argc > 1) {
if (argc > 1)
{
num_elements_per_proc = atoi(argv[1]);
}

Expand All @@ -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();
}
29 changes: 29 additions & 0 deletions NSDS/MPI/NSDS_MPI_tutorial/src/avoiding_deadlock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <mpi.h>
#include <stdio.h>

// 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();
}
77 changes: 64 additions & 13 deletions NSDS/MPI/NSDS_MPI_tutorial/src/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,97 @@
#include <mpi.h>

// 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<num_elements; i++) {
int *create_random_array(int num_elements, int max_value)
{
int *arr = (int *)malloc(sizeof(int) * num_elements);
for (int i = 0; i < num_elements; i++)
{
arr[i] = (rand() % max_value);
}
return arr;
}

// gets an array of ints and a number and returns an array containing only the
// elements that are multiples of the number
// without knowing how many elements will be in the filtered array
void filter_array_by_multiples_of_n(int *array, int array_size, int n)
{
for (int i = 0; i < array_size; i++)
{
if (array[i] % n != 0)
{
array[i] = -1;
}
}
}

// Process 0 selects a number num.
// All other processes have an array that they filter to only keep the elements
// that are multiples of num.
// Process 0 collects the filtered arrays and print them.
int main(int argc, char** argv) {
int main(int argc, char **argv)
{
// Maximum value for each element in the arrays
const int max_val = 100;
// Number of elements for each processor
int num_elements_per_proc = 50;
// Number to filter by
int num_to_filter_by = 2;
if (argc > 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;
}
8 changes: 7 additions & 1 deletion NSDS/MPI/NSDS_MPI_tutorial/src/hello_world.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#include <mpi.h>
#include <stdio.h>

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);

Expand All @@ -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;
Expand Down
30 changes: 26 additions & 4 deletions NSDS/MPI/NSDS_MPI_tutorial/src/ping_pong.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
10 changes: 10 additions & 0 deletions NSDS/MPI/NSDS_MPI_tutorial/src/probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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<num_msgs; i++) {
printf("Received message: %d\n", msgs[i]);
}
free(msgs);
}

MPI_Finalize();
Expand Down
24 changes: 18 additions & 6 deletions NSDS/MPI/NSDS_MPI_tutorial/src/ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

// Send a message in a ring starting from process 0 and increment by one at each hop.
// When the message gets back to process 0, print the number of hops.
int main(int argc, char** argv) {
int main(int argc, char **argv)
{
MPI_Init(NULL, NULL);

int my_rank, world_size;
Expand All @@ -13,11 +14,22 @@ int main(int argc, char** argv) {

int num_hops = 0;

// TODO

if (my_rank == 0) {
printf("Final number of hops in process %d = %d\n", my_rank, num_hops);
while (num_hops < world_size)
{
int hop = 0;
MPI_Recv(&hop, 1, MPI_INT, (my_rank - 1), 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
if (my_rank == 0 && hop == 0)
{
MPI_Send(&num_hops, 1, MPI_INT, (my_rank + 1), 0, MPI_COMM_WORLD);
}
num_hops = hop + 1;
if (my_rank == 0)
{
printf("Number of hops in process %d = %d\n", my_rank, num_hops);
break;
}
MPI_Send(&num_hops, 1, MPI_INT, (my_rank + 1) % world_size, 0, MPI_COMM_WORLD);
}

MPI_Finalize();
}

0 comments on commit 1328f59

Please sign in to comment.