Below is the file 'aca319/lab9q1.c' from this revision. You can also download the file.
#include <stdio.h> #include <stdlib.h> #include <assert.h> #include <string.h> #include <unistd.h> #include <math.h> #include "mpi.h" #include "mpe.h" #define TRACK_SIZE 50 #define ACCELERATION_RATE 10 #define BREAK_RATE 10 #define SPEED_LIMIT 30 #define BREAK_DISTANCE 2 #define ACCELERATE_DISTANCE 5 #define INSPECT_RANK 255 struct car { int track_pos; int speed; int next_car_pos; }; void drive(struct car *c, int rank, int size) { MPI_Status status; int distance; int send_to; /* firstly, we determine what our speed for this time * interval will be, based on our distance to the next * car on the track */ if (c->next_car_pos > c->track_pos) { distance = c->next_car_pos - c->track_pos; } else { distance = (TRACK_SIZE - c->track_pos - 1) + c->next_car_pos; } if (rank == INSPECT_RANK) printf("[%d] (before) position=%d, speed=%d, distance=%d\n", rank, c->track_pos, c->speed, distance); if (distance <= BREAK_DISTANCE) { c->speed -= BREAK_RATE; } else if (distance >= ACCELERATE_DISTANCE) { c->speed += ACCELERATION_RATE; } /* no speeding! */ if (c->speed > SPEED_LIMIT) c->speed = SPEED_LIMIT; /* no going backwards, either */ if (c->speed < 0) c->speed = 0; /* ensure we don't overtake */ if (c->speed > distance - 1) c->speed = distance - 1; /* then we move */ c->track_pos = (c->track_pos + c->speed) % TRACK_SIZE; if (rank == INSPECT_RANK) printf("[%d] (after) position=%d, speed=%d\n", rank, c->track_pos, c->speed); /* then we send our position to the car behind us, and * receive the car in front's position */ send_to = rank - 1; if (send_to < 0) send_to = size - 1; MPI_Sendrecv(&c->track_pos, 1, MPI_INT, send_to, 50, &c->next_car_pos, 1, MPI_INT, (rank + 1) % size, 50, MPI_COMM_WORLD, &status); //printf("%d: at %d, next car at %d\n", rank, c->track_pos, c->next_car_pos); } int main(int argc, char *argv[]) { int rank, size; struct car this_car; char *track; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); /* we're going to start 'size' cars. * they are evenly spaced around the track. */ this_car.track_pos = rank * (TRACK_SIZE / size); this_car.next_car_pos = (rank + 1 % size) * (TRACK_SIZE / size); this_car.speed = 0; if (rank == 0) { track = malloc(sizeof(char) * TRACK_SIZE); if (!track) { fprintf(stderr, "Unable to allocate track array.\n"); return -1; } } for (;;) { /* every processor element updates, and exchanges information * to satisfy data dependency */ drive(&this_car, rank, size); /* processor 0 outputs the track state, all other processors * send their state to 0 */ if (rank == 0) { int i, position; MPI_Status status; memset(track, 0, TRACK_SIZE * sizeof(char)); track[this_car.track_pos] = '0'; for (i=1;i<size;i++) { MPI_Recv(&position, 1, MPI_INT, i, 60, MPI_COMM_WORLD, &status); if (i < 10) { track[position] = 0x30 + i; } else { track[position] = 'A' + (i-10); } } for (i=0;i<TRACK_SIZE;i++) { if (track[i] != 0) { printf("%c", track[i]); } else { printf("-"); } } fflush(stdout); printf("\n\n"); } else { MPI_Send(&this_car.track_pos, 1, MPI_INT, 0, 60, MPI_COMM_WORLD); } sleep(1); } if (rank == 0) { free(track); } MPI_Finalize(); return 0; }