diff --git a/cs677/final/mpi-fractals.cc b/cs677/final/mpi-fractals.cc index 256ed99..9a31fab 100644 --- a/cs677/final/mpi-fractals.cc +++ b/cs677/final/mpi-fractals.cc @@ -22,7 +22,8 @@ bool createWindow(int width, int height, SDL_Surface ** screen, Uint32 ** pixels); void getSizes(int * rank, int * size, int * nprocs); void draw(int rank, int world_size, int nprocs, int width, int height, - Uint32 * pixels, Computation * computation); + Uint32 * pixels, Uint32 * taskVals, Computation * computation); +void sendWindowVals(double * winVals, int world_size); static double x_center = 0.0; static double y_center = 0.0; @@ -76,6 +77,8 @@ int main(int argc, char * argv[]) break; } + unsigned int * taskVals = new unsigned int[width + 1]; + double window_vals[4]; if (my_rank == 0) { SDL_Event event; @@ -86,12 +89,18 @@ int main(int argc, char * argv[]) if (!window_success) going = false; + /* master loop */ while (going && SDL_WaitEvent(&event) != 0) { if (redraw) { + window_vals[0] = 0.0; + window_vals[1] = x_center; + window_vals[2] = y_center; + window_vals[3] = zoom; + sendWindowVals(&window_vals[0], world_size); draw(my_rank, world_size, nprocs, width, height, - pixels, computation); + pixels, taskVals, computation); redraw = false; } SDL_UpdateRect(screen, 0, 0, 0, 0); @@ -130,7 +139,27 @@ int main(int argc, char * argv[]) break; } } + window_vals[0] = 1.0; + sendWindowVals(&window_vals[0], world_size); } + else + { + /* slave loop */ + for (;;) + { + /* wait for a redraw or quit command */ + MPI_Recv(&window_vals[0], 4, MPI_DOUBLE, + MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, NULL); + if (window_vals[0] != 0.0) + break; + x_center = window_vals[1]; + y_center = window_vals[2]; + zoom = window_vals[3]; + draw(my_rank, world_size, nprocs, width, height, + NULL, taskVals, computation); + } + } + delete[] taskVals; MPI_Finalize(); @@ -195,8 +224,9 @@ void getSizes(int * rank, int * size, int * nprocs) } void draw(int rank, int world_size, int nprocs, int width, int height, - Uint32 * pixels, Computation * computation) + Uint32 * pixels, Uint32 * taskVals, Computation * computation) { + MPI_Status mpi_status; if (world_size == 1) { for (int y = 0; y < height; y++) @@ -211,22 +241,70 @@ void draw(int rank, int world_size, int nprocs, int width, int height, } else if (rank == 0) { + int done_val = -1; int num_pixels = width * height; + int pixel = 0; for (int to_proc = 1; to_proc < world_size; to_proc++) { + if (pixel < num_pixels) + { + MPI_Send(&pixel, 1, MPI_INT, to_proc, 0, MPI_COMM_WORLD); + pixel += TASK_SIZE; + } + else + { + MPI_Send(&done_val, 1, MPI_INT, to_proc, 0, MPI_COMM_WORLD); + } + } + int num_tasks = (num_pixels + TASK_SIZE - 1) / TASK_SIZE; + for (int received = 0; received < num_tasks; received++) + { + MPI_Recv(taskVals, width + 1, MPI_INT, + MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &mpi_status); + if (pixel < num_pixels) + { + MPI_Send(&pixel, 1, MPI_INT, + mpi_status.MPI_SOURCE, 0, MPI_COMM_WORLD); + pixel += TASK_SIZE; + } + else + { + MPI_Send(&done_val, 1, MPI_INT, + mpi_status.MPI_SOURCE, 0, MPI_COMM_WORLD); + } + memcpy(pixels + taskVals[0], taskVals + 1, width * sizeof(int)); } } else { for (;;) { + int pixel_num; /* wait to be told what to do */ -#if 0 - MPI_Recv(); - if () /* exit if we are done */ + MPI_Recv(&pixel_num, 1, MPI_INT, + MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, NULL); + if (pixel_num < 0) /* exit if we are done */ break; - MPI_Send(); /* report results back */ -#endif + for (int i = 0; i < TASK_SIZE; i++) + { + int this_pixel_num = pixel_num + i; + int x = this_pixel_num % width; + int y = this_pixel_num / width; + double x_virt = getXVirt(x); + double y_virt = getYVirt(y); + pixels[this_pixel_num] = computation->compute(x_virt, y_virt); + } + /* send the computed pixel data to the master node */ + MPI_Send(pixels, TASK_SIZE, MPI_INT, 0, 0, MPI_COMM_WORLD); } } } + +void sendWindowVals(double * winVals, int world_size) +{ + for (int to_proc = 1; to_proc < world_size; to_proc++) + { + MPI_Send(winVals, 4, MPI_DOUBLE, to_proc, + 0, MPI_COMM_WORLD); + } +}