示例#1
0
文件: main.c 项目: mylove9739/n-body
int main(int   argc,    char *argv[]) {
    init_list_body_data();


    int  nbodies, x, y;
    Window win; // initialization for a window
    GC gc; // graphics context
    Display *display = NULL;
    unsigned int width = X_RESN, height = Y_RESN; /* window size */
    clock_t start, end, elapsed;



    int rank;
    int size;

    MPI_Init (&argc, &argv);      /* starts MPI */
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);        /* get current process id */
    MPI_Comm_size(MPI_COMM_WORLD, &size);        /* get number of processes */



    // I follow this topic
    // http://stackoverflow.com/questions/9864510/struct-serialization-in-c-and-transfer-over-mpi
    // alow MPI tranfer truct data type
    const int       num_of_item = 8;
    int             blocklengths[8] = {1, 1, 1, 1, 1, 1, 1, 1};
    MPI_Datatype    types[8] = {MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_INT};
    MPI_Datatype    mpi_body_type;
    MPI_Aint        offsets[8];

    offsets[0] = offsetof(body, position_x);
    offsets[1] = offsetof(body, position_y);
    offsets[2] = offsetof(body, velocity_x);
    offsets[3] = offsetof(body, velocity_y);
    offsets[4] = offsetof(body, force_x);
    offsets[5] = offsetof(body, force_y);
    offsets[6] = offsetof(body, mass);
    offsets[7] = offsetof(body, body_id);

    MPI_Type_create_struct(num_of_item, blocklengths, offsets, types, &mpi_body_type);
    MPI_Type_commit(&mpi_body_type);





    //
    // http://stackoverflow.com/questions/11246150/synchronizing-master-slave-model-with-mpi
    // for master/slave
    int j = 0;
    int i = 0;
    int k = 0;
    int num_of_move =100;
    int index = 0;
    int p;


    int steps = MAX_BODY / (size - 1);

    if (( MAX_BODY % (size - 1)) > 0) {
        steps++;
    }
    if(rank == 0)
    {
        display = x11setup(&win, &gc, width, height);
        // other setup code in the master
    }
    for (j = 0; j < num_of_move; j++) {
        //which number of moves  process complte!?
        if(rank == 0) {
            printf("Processed %d of %d\n", j, num_of_move);
        }
        for (k = 0; k < MAX_BODY; k ++) {

            index = 0;
            for (i = 0; i <  steps; i++ ) {

                if(rank == 0) { //master
                    for(p = 1; p < size; p++){

                        body a =  list_body[k];
                        body b =  list_body[index];
                        if (index >= MAX_BODY -1) {
                            b = list_body[MAX_BODY -1];
                        }
                        // send 2 body to calculate force
                        MPI_Send(&a, 1, mpi_body_type, p, 20, MPI_COMM_WORLD);
                        MPI_Send(&b, 1, mpi_body_type, p, 20, MPI_COMM_WORLD);

                        //recieve result
                        body b_recv;
                        MPI_Recv(&b_recv, 1, mpi_body_type, p, 21, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

                        //update to list
                        list_body[k] = b_recv;
                        index++;
                    }

                }
                else { //workers

                    //receive 2 body to calculate force
                    body  a;
                    MPI_Recv(&a, 1, mpi_body_type, 0, 20, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
                    body  b;
                    MPI_Recv(&b, 1, mpi_body_type, 0, 20, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

                    // calculating....
                    update_body_force(&a, &b);
                    update_body_velocity(&a);
                    update_body_location(&a);

                    // finish! send body a to master
                    MPI_Send(&a, 1, mpi_body_type, 0, 21, MPI_COMM_WORLD);
                }
            }
        }
        if(rank == 0) {
            XClearWindow(display, win);
            for (i = 0; i < MAX_BODY; i++) { // draw the bodies on the display
                body b = list_body[i];
                // this function will draw a circle inside a 3x3 box with the upper left
                // corner at (x,y). N.b. the last 2 arguments mean that it will fill from
                // 0 to 360 degrees - a full circle
                if (i == 0) {
                    XFillArc(display, win, gc, b.position_x , b.position_y, 6, 6, 0, 23040);
                }
                XFillArc(display, win, gc, b.position_x , b.position_y, 3, 3, 0, 23040);

                // you campicould also use XDrawPoint(display, win, gc, x, y) to draw a single
                // pixel at (x,y)
            }
            XFlush(display);
            //reset force
            for (i = 0; i < MAX_BODY; i++) {
                    body *b = & list_body[i];

                    b->force_x = 0;
                    b->force_y = 0;
            }

        }


        usleep(100 * 1000);

    }
    // finaly, use rank=0 (master) to output result
    if (rank == 0) {
        i = 0;
        for (i = 0; i < MAX_BODY; i++) {
            body_info(list_body[i]);
        }
    }



    // main loop
//    int running = 1; // loop variable
//    start = clock();
//    while(running) {

//        // checks to see if there have been any events,
//        // will exit the main loop if any key is pressed
//        if(rank==0) {
//            if(XPending(display)) {
//                XEvent ev;
//                XNextEvent(display, &ev);
//                switch(ev.type) {
//                    case KeyPress:
//                        running = 0;
//                        break;
//                }
//            }
//        }


        // your code to calculate the forces on the bodies goes here


//        end = clock();
//        elapsed = end - start;
//        // only update the display if > 1 millisecond has passed since the last update
//        if(elapsed / (CLOCKS_PER_SEC/1000) > 1 && rank==0) {
//            XClearWindow(display, win);
//            for (i = 0; i < MAX_BODY; i++) { // draw the bodies on the display
//                body b = list_body[i];
//                // this function will draw a circle inside a 3x3 box with the upper left
//                // corner at (x,y). N.b. the last 2 arguments mean that it will fill from
//                // 0 to 360 degrees - a full circle
//                XFillArc(display, win, gc, b.position_x , b.position_y, 3, 3, 0, 23040);

//                // you campicould also use XDrawPoint(display, win, gc, x, y) to draw a single
//                // pixel at (x,y)
//            }
//            start = end;
//            XFlush(display);
//        }
//    }

//    if(rank==0 && display) {
//        XCloseDisplay(display); // close the display window
//    }


    MPI_Finalize();


    return EXIT_SUCCESS;
}
int main(int argc, char *argv[]) {
	int rank, nprocs, x, y;
	Window win; // initialization for a window
	GC gc; // graphics context
	Display *display = NULL;
	Colormap screenColourmap;
	XColor colours[15];
	unsigned int width = X_RESN, height = Y_RESN; /* window size */
	clock_t start, end, elapsed;
	int pixelToDraw[3];
	MPI_Init(&argc, &argv); 
	MPI_Comm_size(MPI_COMM_WORLD, &nprocs); 
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);

	ComplexNumber c;
	ComplexNumber z;
	int depth = 1000;
	int cSize = 4;
	double cX = -2;
	double cY = -2;
	double cMinR = cX;
	double cMinI = cY;
	double cMaxR = cMinR + cSize;
	double cMaxI = cMinI + cSize;
	double increaseX = (cMaxR - cMinR) / X_RESN;
	double increaseY = (cMaxI - cMinI) / Y_RESN;
	int drawable[X_RESN][Y_RESN];
        
	if(rank==0)
	{
		display = x11setup(&win, &gc, width, height);
		screenColourmap = DefaultColormap(display, DefaultScreen(display));
		setupColours(display, colours, screenColourmap);
		int probeFlag = 0;
		MPI_Status status;
		int count = 0;
		int start = 1;
		for (int i = 1; i < nprocs; i++) {
			MPI_Send(&start, 1, MPI_INT, i, 98, MPI_COMM_WORLD);
		}
		for (int y = 0; y < Y_RESN; y++) {
			for (int x = 0; x < X_RESN; x++) {
				while (!probeFlag) {
					MPI_Iprobe(MPI_ANY_SOURCE, 99, MPI_COMM_WORLD, &probeFlag, &status);
					if (probeFlag) {
						int coords[2] = {x, y};
						int slave = status.MPI_SOURCE;
						MPI_Recv(&pixelToDraw, 3, MPI_INT, MPI_ANY_SOURCE, 99, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
						MPI_Send(&coords, 2, MPI_INT, slave, 99, MPI_COMM_WORLD); 
						drawable[pixelToDraw[0]][pixelToDraw[1]] = pixelToDraw[2];
						count++;
					} else {
						MPI_Iprobe(MPI_ANY_SOURCE, 98, MPI_COMM_WORLD, &probeFlag, &status);
						if (probeFlag) {
							int slave = status.MPI_SOURCE;
							int coords[2] = {x, y};
							MPI_Recv(&start, 1, MPI_INT, MPI_ANY_SOURCE, 98, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
							MPI_Send(&coords, 2, MPI_INT, slave, 99, MPI_COMM_WORLD); 
						}
					}
				}
				probeFlag = 0;
			}
		}
		MPI_Recv(&pixelToDraw, 3, MPI_INT, MPI_ANY_SOURCE, 99, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
		drawable[pixelToDraw[0]][pixelToDraw[1]] = pixelToDraw[2];
		for (int y = 0; y < Y_RESN; y++) {
			for (int x = 0; x < X_RESN; x++) {
				drawPoint(display, win, gc, colours, x, y, depth, drawable[x][y]);
			}
		}
	} else {
		int flag = 1;
		int coords[2];
		MPI_Recv(&start, 1, MPI_INT, 0, 98, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
		MPI_Send(&start, 1, MPI_INT, 0, 98, MPI_COMM_WORLD);
		while (flag) {
			MPI_Recv(&coords, 2, MPI_INT, 0, 99, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
			c.r = coords[0] * increaseX - 2;
			c.i = coords[1] * increaseY - 2;
			resetComplexNumber(&z);
			int limit = seriesDiverges(depth, &z, &c);
			pixelToDraw[0] = coords[0];
			pixelToDraw[1] = coords[1];
			pixelToDraw[2] = limit;
			MPI_Send(&pixelToDraw, 3, MPI_INT, 0, 99, MPI_COMM_WORLD);
		}
	}
	
	// main loop
	int running = 1; // loop variable
	start = clock();
	while(running) {
	
		// checks to see if there have been any events,
		// will exit the main loop if any key is pressed
		if(rank==0) {
			if(XPending(display)) {
				XEvent ev;
				XNextEvent(display, &ev);
				switch(ev.type) {
					case KeyPress:
						running = 0;
						break;
				}
			}
		}
		
		end = clock();
		elapsed = end - start;
		// only update the display if > 1 millisecond has passed since the last update
		if(elapsed / (CLOCKS_PER_SEC/1000) > 1 && rank==0) {
			//XClearWindow(display, win);
			start = end;
			XFlush(display);
		}
	}

	if(rank==0 && display) {
		XCloseDisplay(display); // close the display window
		printf("Display closed\n");
	} else {
		MPI_Finalize();
		return 0;
	}
	
	MPI_Finalize();
	return 0;
}