-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7c9f2e2
commit 4a94fd3
Showing
3 changed files
with
340 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |