Skip to content

Commit

Permalink
mpi lab
Browse files Browse the repository at this point in the history
  • Loading branch information
PietroPizzoccheri committed Dec 4, 2024
1 parent 7c9f2e2 commit 4a94fd3
Show file tree
Hide file tree
Showing 3 changed files with 340 additions and 0 deletions.
150 changes: 150 additions & 0 deletions NSDS/MPI/NSDS_MPI_lab/guess.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int rank;
int num_procs;

const int num_rounds = 10;

const int min_num = 1;
const int max_num = 1000;

// Array, one element per process
// The leader board, instantiated and used in process 0
int *leaderboard = NULL;

// Array, one element per process
// The array of number selected in the current round
int *selected_numbers = NULL;

// The leader for the current round
int leader = 0;

// Allocate dynamic variables
void allocate_vars()
{
leaderboard = (int *)malloc(num_procs * sizeof(int));
selected_numbers = (int *)malloc(num_procs * sizeof(int));
memset(leaderboard, 0, num_procs * sizeof(int));
memset(selected_numbers, 0, num_procs * sizeof(int));
}

// Deallocate dynamic variables
void free_vars()
{
free(leaderboard);
free(selected_numbers);
}

// Select a random number between min_num and max_num
int select_number()
{
return min_num + rand() % (max_num - min_num + 1);
}

// Function used to communicate the selected number to the leader
void send_num_to_leader(int num)
{
MPI_Send(&num, 1, MPI_INT, leader, 0, MPI_COMM_WORLD);
}

// Compute the winner (-1 if there is no winner)
// Function invoked by the leader only
int compute_winner(int number_to_guess)
{
int diff = 0;
int min_diff = max_num; // the difference cannot be larger than the max_num used to generte the random number
int new_leader = -1;
for (int i = 0; i < num_procs; i++)
{
diff = abs(selected_numbers[i] - number_to_guess);
if (diff < min_diff)
{
min_diff = diff;
new_leader = i;
}
}
return new_leader;
}

// Function used to communicate the winner to everybody
void send_winner(int *winner)
{
MPI_Bcast(winner, 1, MPI_INT, leader, MPI_COMM_WORLD);
}

// Update leader
void update_leader(int winner)
{
if(winner != -1)
leader = winner;
}

// Update leaderboard (invoked by process 0 only)
void update_leaderboard(int winner)
{
leaderboard[winner]++;
}

// Print the leaderboard
void print_leaderboard(int round, int winner)
{
printf("\n* Round %d *\n", round);
printf("Winner: %d\n", winner);
printf("Leaderboard\n");
for (int i = 0; i < num_procs; i++)
{
printf("P%d:\t%d\n", i, leaderboard[i]);
}
}

void receive_numbers()
{
for (int i = 0; i < num_procs; i++)
{
MPI_Status status;
MPI_Probe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
int source = status.MPI_SOURCE;
MPI_Recv((selected_numbers + source), 1, MPI_INT, source, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
}

int main(int argc, char **argv)
{
MPI_Init(NULL, NULL);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
srand(time(NULL) + rank);

allocate_vars();
int winner;
for (int round = 0; round < num_rounds; round++)
{
int my_selected_number = select_number();

send_num_to_leader(my_selected_number);

if (rank == leader)
{
receive_numbers();
int number_to_guess = select_number();
winner = compute_winner(number_to_guess); // computes winner against number selected by winner
}
send_winner(&winner);
update_leader(winner);

if (rank == 0)
{
update_leaderboard(winner);
print_leaderboard(round, winner);
}
}

MPI_Barrier(MPI_COMM_WORLD);
free_vars();

MPI_Finalize();
}
146 changes: 146 additions & 0 deletions NSDS/MPI/NSDS_MPI_lab/linear_road.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/**
* Group number:
*
* Group members
* Member 1
* Member 2
* Member 3
*
**/

// Set DEBUG 1 if you want car movement to be deterministic
#define DEBUG 0

const int num_segments = 256;
const int num_iterations = 1000;
const int count_every = 10;
const double alpha = 0.5;
const int max_in_per_sec = 10;

// Returns the number of car that enter the first segment at a given iteration.
int create_random_input()
{
if (DEBUG)
{
return 1;
}
else
{
return rand() % max_in_per_sec;
}
}

// Returns 1 if a car needs to move to the next segment at a given iteration, 0 otherwise.
int move_next_segment()
{
if (DEBUG)
{
return 1;
}
else
{
return rand() < alpha * RAND_MAX ? 1 : 0;
}
}

void initialize_segments(int *segments, int segs_per_proc)
{
memset(segments, 0, segs_per_proc * sizeof(int));
}

void move_cars(int *segments, int segs_per_proc, int rank, int num_procs)
{
for (int i = 0; i < segs_per_proc; ++i)
{
int cars_moving = 0;
for (int j = 0; j < segments[i]; j++)
{
if (move_next_segment())
cars_moving++;
}

segments[i] -= cars_moving;

if (i < segs_per_proc - 1)
{
segments[i + 1] += cars_moving;
}
else if (i == segs_per_proc - 1 && rank < num_procs - 1)
{
MPI_Request request;
MPI_Isend(&cars_moving, 1, MPI_INT, rank + 1, 0, MPI_COMM_WORLD, &request);
}
}
}

void receive_cars(int *segments, int rank)
{
int cars_received_to_first = 0;
if (rank != 0)
{
MPI_Request request;
MPI_Irecv(&cars_received_to_first, 1, MPI_INT, rank - 1, 0, MPI_COMM_WORLD, &request);
MPI_Wait(&request, MPI_STATUS_IGNORE);
}
else
{
cars_received_to_first = create_random_input();
}
segments[0] += cars_received_to_first;
}

void compute_and_print_global_sum(int *segments, int segs_per_proc, int rank, int iteration)
{
int my_sum = 0;
for (int i = 0; i < segs_per_proc; i++)
my_sum += segments[i];

int global_sum = 0;
MPI_Reduce(&my_sum, &global_sum, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);

if (rank == 0)
{
printf("Iteration: %d, sum: %d\n", iteration, global_sum);
}
}

void simulate_traffic(int *segments, int segs_per_proc, int rank, int num_procs)
{
for (int it = 0; it < num_iterations; ++it)
{
move_cars(segments, segs_per_proc, rank, num_procs);
receive_cars(segments, rank);

if (it % count_every == 0)
{
compute_and_print_global_sum(segments, segs_per_proc, rank, it);
}

MPI_Barrier(MPI_COMM_WORLD);
}
}

int main(int argc, char **argv)
{
MPI_Init(NULL, NULL);

int rank, num_procs;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
srand(time(NULL) + rank);

int segs_per_proc = num_segments / num_procs;
int cars_my_segments[segs_per_proc];

initialize_segments(cars_my_segments, segs_per_proc);
simulate_traffic(cars_my_segments, segs_per_proc, rank, num_procs);

MPI_Finalize();
return 0;
}
44 changes: 44 additions & 0 deletions NSDS/MPI/NSDS_MPI_lab/monte_carlo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <mpi.h>

const int num_iter_per_proc = 10 * 1000 * 1000;

int main()
{
MPI_Init(NULL, NULL);

int rank;
int num_procs;
int sum;
int sum_global = 0;

MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);

srand(time(NULL) + rank);

for (int i = 0; i < num_iter_per_proc; i++)
{
double x = (double)rand() / RAND_MAX;
double y = (double)rand() / RAND_MAX;
if (x * x + y * y <= 1)
{
sum++;
}
}

MPI_Reduce(&sum, &sum_global, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);

if (rank == 0)
{
printf("%d\n", sum_global);
printf("%d\n", sum);
double pi = (4.0 * (sum_global)) / (num_iter_per_proc * num_procs);
printf("Pi = %f\n", pi);
}

MPI_Finalize();
return 0;
}

0 comments on commit 4a94fd3

Please sign in to comment.