diff --git a/NSDS/MPI/NSDS_MPI_lab/guess.c b/NSDS/MPI/NSDS_MPI_lab/guess.c new file mode 100644 index 0000000..af85999 --- /dev/null +++ b/NSDS/MPI/NSDS_MPI_lab/guess.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include + +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(); +} diff --git a/NSDS/MPI/NSDS_MPI_lab/linear_road.c b/NSDS/MPI/NSDS_MPI_lab/linear_road.c new file mode 100644 index 0000000..7b22801 --- /dev/null +++ b/NSDS/MPI/NSDS_MPI_lab/linear_road.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include + +/** + * 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; +} \ No newline at end of file diff --git a/NSDS/MPI/NSDS_MPI_lab/monte_carlo.c b/NSDS/MPI/NSDS_MPI_lab/monte_carlo.c new file mode 100644 index 0000000..32ae567 --- /dev/null +++ b/NSDS/MPI/NSDS_MPI_lab/monte_carlo.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +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; +}