#include "mpi.h" #include extern void draw_heat(int, int); /* X routine to create graph */ #define NXPROB 20 /* x dimension of problem grid */ #define NYPROB 20 /* y dimension of problem grid */ #define STEPS 50 /* number of time steps */ #define MAXWORKER 8 /* maximum number of worker tasks */ #define MINWORKER 3 /* minimum number of worker tasks */ #define BEGIN 1 /* message type */ #define NGHBOR1 2 /* message type */ #define NGHBOR2 3 /* message type */ #define NONE 0 /* indicates no neighbor */ #define DONE 4 /* message type */ #define MASTER 0 /* taskid of first process */ struct Parms { float cx; float cy; } parms = {0.1, 0.1}; int main(argc,argv) int argc; char *argv[]; { void inidat(), prtdat(), update(); float u[2][NXPROB][NYPROB]; /* array for grid */ int taskid, /* this task's unique id */ numworkers, /* number of worker processes */ numtasks, /* number of tasks */ averow,rows,offset,extra, /* for sending rows of data */ dest, source, /* to - from for message send-receive */ neighbor1,neighbor2, /* neighbor tasks */ msgtype, /* for message types */ rc,start,end, /* misc */ i,ix,iy,iz,it; /* loop variables */ MPI_Status status; /* First, find out my taskid and how many tasks are running */ rc = MPI_Init(&argc,&argv); rc|= MPI_Comm_size(MPI_COMM_WORLD,&numtasks); rc|= MPI_Comm_rank(MPI_COMM_WORLD,&taskid); if (rc != 0) printf ("error initializing MPI and obtaining task ID information\n"); else printf ("mpi_heat2D MPI task ID = %d\n", taskid); numworkers = numtasks-1; if (taskid == MASTER) { /************************* master code *******************************/ /* Check if numworkers is within range - quit if not */ if ((numworkers > MAXWORKER) || (numworkers < MINWORKER)) { printf("MP_PROCS needs to be between %d and %d for this exercise\n", MINWORKER+1,MAXWORKER+1); MPI_Finalize(); } /* Initialize grid */ printf("Grid size: X= %d Y= %d Time steps= %d\n",NXPROB,NYPROB,STEPS); printf("Initializing grid and writing initial.dat file...\n"); inidat(NXPROB, NYPROB, u); prtdat(NXPROB, NYPROB, u, "initial.dat"); /* Distribute work to workers. Must first figure out how many rows to */ /* send and what to do with extra rows. */ averow = NXPROB/numworkers; extra = NXPROB%numworkers; offset = 0; for (i=1; i<=numworkers; i++) { rows = (i <= extra) ? averow+1 : averow; /* Tell each worker who its neighbors are, since they must exchange */ /* data with each other. */ if (i == 1) neighbor1 = NONE; else neighbor1 = i - 1; if (i == numworkers) neighbor2 = NONE; else neighbor2 = i + 1; /* Now send startup information to each worker */ dest = i; MPI_Send(&offset, 1, MPI_INT, dest, BEGIN, MPI_COMM_WORLD); MPI_Send(&rows, 1, MPI_INT, dest, BEGIN, MPI_COMM_WORLD); MPI_Send(&neighbor1, 1, MPI_INT, dest, BEGIN, MPI_COMM_WORLD); MPI_Send(&neighbor2, 1, MPI_INT, dest, BEGIN, MPI_COMM_WORLD); MPI_Send(&u[0][offset][0], rows*NYPROB, MPI_FLOAT, dest, BEGIN, MPI_COMM_WORLD); printf("Sent to= %d offset= %d rows= %d neighbor1= %d neighbor2= %d\n", dest,offset,rows,neighbor1,neighbor2); offset = offset + rows; } /* Now wait for results from all worker tasks */ for (i=1; i<=numworkers; i++) { source = i; msgtype = DONE; MPI_Recv(&offset, 1, MPI_INT, source, msgtype, MPI_COMM_WORLD, &status); MPI_Recv(&rows, 1, MPI_INT, source, msgtype, MPI_COMM_WORLD, &status); MPI_Recv(&u[0][offset][0], rows*NYPROB, MPI_FLOAT, source, msgtype, MPI_COMM_WORLD, &status); } /* Write final output and call X graph */ printf("Writing final.dat file and generating graph...\n"); prtdat(NXPROB, NYPROB, &u[0][0][0], "final.dat"); draw_heat(NXPROB,NYPROB); } /* End of master code */ if (taskid != MASTER) { /************************* worker code **********************************/ /* Initialize everything - including the borders - to zero */ for (iz=0; iz<2; iz++) for (ix=0; ix= 0; iy--) { for (ix = 0; ix <= nx-1; ix++) { fprintf(fp, "%6.1f", *(u1+ix*ny+iy)); if (ix != nx-1) fprintf(fp, " "); else fprintf(fp, "\n"); } } fclose(fp); }