/* Jeffrey Grafton 10/1/2002 This program is released under the GNU General Public License. A copy of this license is available online at http://www.gnu.org/copyleft/gpl.html. */ #include #include #include #include #include #define MINX -1.0 #define MINY -1.0 #define MAXX 1.0 #define MAXY 1.0 #define WINDOW_WIDTH 300 #define WINDOW_HEIGHT 300 #define MAX_MOVES 50000 #define WORK_MSG 1 #define RESULT_MSG 2 #define DONE_MSG 3 typedef struct { double x[500]; double y[500]; int numpoints; } Point; typedef struct { double column; double colors[WINDOW_WIDTH][3]; } row; void display_init(void); void display(void); void draw_graph(void); void master(int, char **); void slave(int); void send_work(void); void draw_screen(void); void do_work(row *); void DrawMyStuff (void); int main (int argc, char *argv[]) { int my_rank; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); if (my_rank == 0) { master(argc, argv); } else { slave(my_rank); } MPI_Finalize(); return 0; } void master(int argc, char **argv) { printf("master: running\n"); glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); glutCreateWindow("julia"); display_init(); glutDisplayFunc(display); glutMainLoop(); } void slave(int my_rank) { Point coord; double i, range[2]; int number_tasks; int count; MPI_Status status; printf("slave: running\n"); MPI_Comm_size(MPI_COMM_WORLD, &number_tasks); // while (1) // { MPI_Recv(&range, 2, MPI_DOUBLE, 0, WORK_MSG, MPI_COMM_WORLD, &status); count=0; for (i = range[0]; i < range[1]; i += (MAXX - MINX) / (WINDOW_WIDTH)) { coord.x[count] = i; coord.y[count] = 4* i - 4* i * i ; // Calculate y value of parabola count++; } coord.numpoints=count; MPI_Send(&coord, sizeof(coord), MPI_BYTE, 0, RESULT_MSG, MPI_COMM_WORLD); // MPI_Send(0, 0, MPI_INT, 0, DONE_MSG, MPI_COMM_WORLD); // } } void DrawAxis() { glColor3f(0.0,0.0,0.0); glBegin(GL_LINES); glVertex2f(MINX,0); glVertex2f(MAXX,0); glVertex2f(0,MINY); glVertex2f(0,MAXY); glEnd(); } /* initialization routines */ void display_init (void) {/* select clearing (background) color */ glClearColor(0.5, 0.5, 0.5, 0.0); // These RGB values make gray /* initialize viewing values */ glMatrixMode(GL_PROJECTION); // Select Matrix Mode glLoadIdentity(); // Provide Base Matrix glOrtho(MINX, MAXX, MINY, MAXY, -1.0, 1.0); // Set window dimensions // Parameters: glOrtho(Left, Right, Bottom, Top, Front, Back) glClear(GL_COLOR_BUFFER_BIT); } /* main display function */ void display (void) { double start_time, end_time; glClear(GL_COLOR_BUFFER_BIT); start_time = MPI_Wtime(); send_work(); DrawAxis(); DrawMyStuff(); // Call my Drawing Routine glFlush(); // Force writing all pending OpenGL actions to the screen. end_time = MPI_Wtime(); printf("master: operation took %f seconds.\n", end_time - start_time); } void send_work (void) { int number_tasks, i; double interval; MPI_Comm_size(MPI_COMM_WORLD, &number_tasks); if (number_tasks < 2) { printf("Please use 2 or more tasks.\n"); exit(1); } interval = (MAXX - MINX) / (number_tasks - 1); for (i = 0; i < number_tasks - 1; i++) { double range[2]; range[0] = i * interval + MINX; range[1] = (i + 1) * interval + MINX; if (i == number_tasks - 2) range[1] = MAXX; MPI_Send(&range, 2, MPI_DOUBLE, i + 1, WORK_MSG, MPI_COMM_WORLD); } } void DrawMyStuff (void) { int i, j, number_tasks; MPI_Status status; Point coord; MPI_Comm_size(MPI_COMM_WORLD, &number_tasks); glColor3f(1.0, 1.0, 0.0); // Set drawing color to yellow glBegin(GL_POINTS); for (i = 1; i < number_tasks; i++ ) { MPI_Recv(&coord, sizeof(coord), MPI_BYTE, i, MPI_ANY_TAG, MPI_COMM_WORLD, &status); /* if (status.MPI_TAG == DONE_MSG) { i++; printf("master: slave finished\n"); continue; } */ for (j = 0; j < coord.numpoints; j++) glVertex3f(coord.x[j], coord.y[j], 0.0); // Plot point at (x,y) z=0 in 2D glFlush(); } glEnd(); glFlush(); }