main(int argc, char* argv[]) { int me, np, i; int x, y, w, h; int x1, y1, x2, y2; int color, button, pressed; int space, num_colors; MPE_Color col_array[64]; /* Color array */ MPE_Point points[80]; /* Array to store 80 pixels in */ w=10; h=20; /* Width and height of colored rectangles */ MPI_Init (&argc, &argv); /* Initialize MPI */ MPI_Comm_size(MPI_COMM_WORLD, &np); /* Get nr of processes */ MPI_Comm_rank(MPI_COMM_WORLD, &me); /* Get own id */ /* Check that we have exactly two processes */ if (np != 2) { if (me == 0) printf("You have to run this program with 2 processes\n"); MPI_Finalize(); exit(0); } if (me == 0) printf("Opening a graphics window\n") ; /* Open the graphics window in position (0,0) on the display */ MPE_Open_graphics(&graph, MPI_COMM_WORLD, displayname, 0, 0, width, height, 0 ); /* Get number of colors */ MPE_Num_colors(graph, &num_colors); if (me == 0) { printf("Number of colors = %d,\n", num_colors) ; } /* Processor 0 puts a pink rectangle of size 100*240 in position (0,0) */ if (me==0) { MPE_Fill_rectangle( graph, 0, 0, 100, 240, MPE_PINK ); MPE_Update( graph ); } /* Both processors draws one rectangle for each colour, placed in a row */ x=0; y=(me)*50; space=2; for (color=0; color<num_colors; color++) { x=x+w+space; /* Set position of rectangles */ MPE_Fill_rectangle( graph, x, y, w, h, color ); } MPE_Update( graph ); /* Create a new color array with 64 colours */ MPE_Make_color_array(graph, 64, col_array); /* Get number of colors */ MPE_Num_colors(graph, &num_colors); if ( me == 0 ) { printf("Number of colors = %d,\n", num_colors) ; } /* Both processors draw one rectangle for each colour, placed in a row */ x=0; y=(me+1)*100; for (color=0; color<num_colors; color++) { x=x+w+space; /* Set position of rectangles */ MPE_Fill_rectangle( graph, x, y, w, h, color ); } MPE_Update( graph ); /* Set lines to be 2 pixels thick */ MPE_Line_thickness(graph, 2); /* Both processes draw a line, each with different color */ MPE_Draw_line(graph, 300+(20*me), 10+(20*me), 800+(20*me), 70+(20*me), 30+(20*me)); MPE_Update( graph ); /* Both processes draw a circle of different size and color */ MPE_Draw_circle(graph, 100+(50*me), 300+(50*me), 20+(5*me), num_colors-(20*me)); MPE_Update(graph); /* Both processes draw 50 pixels with different colors */ for (i=0; i<50; i++) { int rx, ry; rx = 200+rand()%15; /* Random positions where to draw points */ ry = 300+rand()%15+40*me; MPE_Draw_point(graph, rx, ry, num_colors-(20*me)); } MPE_Update(graph); /* Build 80 pixels with randomly chosen colors in the array points */ for (i=0; i<80; i++) { points[i].x = 250+rand()%15; /* Set x coordinate */ points[i].y = 300+rand()%15+40*me; /* Set y coordinate */ points[i].c = rand()%num_colors; /* Set a color */ } MPE_Draw_points(graph, points, 80); /* Draw all 80 points */ MPE_Update(graph); /* Draw a text string */ MPE_Draw_string(graph, 400, 250, MPE_BLACK, "Hello from MPE_Draw_string"); MPE_Update(graph); /* Wait until the user selects a region of the graph, using button 1 */ /* Print out the coordinates of the selected region and draw a black */ /* rectangle around the selected region */ button=1; /* Use button 1 */ if (me==0) { printf("Select a region of the graph using mouse button %d\n", button); MPE_Get_drag_region( graph, button, MPE_DRAG_RECT, &x1, &y1, &x2, &y2 ); printf("Selected region is (%d,%d) to (%d,%d)\n", x1, y1, x2, y2); /* Draw a black rectangle around the selected area */ /* This should of course be implemented in a procedure MPE_Draw_rectangle */ /* Maybe I will write one some day ... */ MPE_Draw_line(graph, x1, y1, x1, y2, MPE_BLACK); MPE_Draw_line(graph, x1, y2, x2, y2, MPE_BLACK); MPE_Draw_line(graph, x2, y2, x2, y1, MPE_BLACK); MPE_Draw_line(graph, x2, y1, x1, y1, MPE_BLACK); MPE_Update(graph); } /* Wait until the user presses a mouse button */ if (me == 0) { printf("Press a mouse button to terminate\n"); MPE_Get_mouse_press(graph, &x, &y, &button); printf("User clicked button %d in position (%d,%d)\n", button, x, y); } /* We can also poll the mouse buttons with MPE_Iget_mouse_pressed */ /* pressed = 0; */ /* if (me == 0) { */ /* do { */ /* MPE_Iget_mouse_press(graph, &x, &y, &button, &pressed); */ /* } while (!pressed); */ /* printf("User clicked button %d in position (%d,%d)\n", button, x, y); */ /* } */ /* Wait here for terminationn signal from process 0 */ /* MPI_Barrier(MPI_COMM_WORLD); */ /* Close the graphics window and terminate */ MPE_Close_graphics(&graph); MPI_Finalize(); exit(0); }
//master process void master(int np) { int window = 0;//which window; int l_sent = 0;//how many lines have sent; int l_recv = 0;//how many lines have received; int i; //the points of a line. MPE_Point* points = (MPE_Point*)malloc(W*sizeof(MPE_Point)); double start, stop; do { start = MPI_Wtime(); window++; //first send a line number to each slave for(i = 1; i < np; i++) { if(l_sent < H) { MPI_Send(&l_sent, 1, MPI_INT, i, tag, MPI_COMM_WORLD); l_sent++; } }; do { /*Receive the result back from the slaves, we use MPI_ANY_SOURCE here because we just receive the result from the fastest slave*/ MPI_Recv(mans, W+1, MPI_INT, MPI_ANY_SOURCE, tag, MPI_COMM_WORLD, &status); /*after we received a computed mandelbrot number of points of a line, the master process begin to draw that line and increase the received lines variable*/ draw_line(mans,points); l_recv++; /*if there are still some rows to send, send the next row to the free slave*/ if(l_sent < H) { MPI_Send(&l_sent, 1, MPI_INT, status.MPI_SOURCE, tag, MPI_COMM_WORLD); l_sent++; } else { /*if we have sent all the rows, then the end signal to the free slave to tell that it can have a rest now. we use -1 which is an impossible line number to represent the end signal */ int endSignal = -1; MPI_Send(&endSignal, 1, MPI_INT, status.MPI_SOURCE, tag, MPI_COMM_WORLD); } } while(l_recv < H);/*if we have received results back of all the rows from slaves, then current window is ready, we can wait for the user to drag an area to zoom in*/ stop = MPI_Wtime(); printf("Window %d takes %f seconds\n", window, stop-start);//how long it takes to draw a window int px, py, rx, ry; /*get the drag region from the user. It is interesting that I found (px,py) is always the lower left poit and (rx, ry) is always the upper right point no matter I drag from left to right or from right to left*/ MPE_Get_drag_region(graph, MPE_BUTTON1, MPE_DRAG_SQUARE, &px, &py, &rx, &ry); /* When the user indicates that it is time to terminate, the master sends a stop-signal to all slaves. User indicates termination by selecting a very small area(less than 10*10 pixels) to zoom in to, e.g. clicks with cursor in the window instead of dragging a square area. */ if((rx-px)*(ry-py) < 10*10) { /* when it is the time to terminate the program, we broadcast the impossible lower left(-3, -3) and upper right point(-3, -3) to indicate the slaves that it is time to terminate. */ min_max[0]=min_max[1]=min_max[2]=min_max[3]=-3.0; MPI_Bcast(min_max, 4, MPI_DOUBLE, 0, MPI_COMM_WORLD); break; } else { /* when user select a area to zoom in, the master recalculate the lower left and upper right points and broadcast these two points to the slaves. */ min_max[0] = real_min + px*real_scale; min_max[1] = real_min + rx*real_scale; min_max[2] = imag_min + py*imag_scale; min_max[3] = imag_min + ry*imag_scale; real_min = min_max[0]; real_max = min_max[1]; imag_min = min_max[2]; imag_max = min_max[3]; real_scale = (real_max - real_min) / (double)W; imag_scale = (imag_max - imag_min) / (double)H; /* reset the send counter and received counter*/ l_sent = 0; l_recv = 0; MPI_Bcast(min_max, 4, MPI_DOUBLE, 0, MPI_COMM_WORLD); } } while(1); free(points); }