int main(void) { MPI_Comm comm; int rank, size; double tstart, tstop, time; char *filename; int xpix, ypix; comm = MPI_COMM_WORLD; MPI_Init(NULL, NULL); MPI_Comm_size(comm, &size); MPI_Comm_rank(comm, &rank); MPI_Barrier(comm); tstart = MPI_Wtime(); filename = "fuzzy.pgm"; if (rank == 0) { printf("\n"); printf("Image sharpening code running on %d processor(s)\n", size); printf("\n"); printf("Input file is: %s\n", filename); pgmsize(filename, &xpix, &ypix); printf("Image size is %d x %d\n", xpix, ypix); printf("\n"); fflush(stdout); } MPI_Bcast(&xpix, 1, MPI_INT, 0, comm); MPI_Bcast(&ypix, 1, MPI_INT, 0, comm); dosharpen(filename, xpix, ypix, comm); MPI_Barrier(comm); tstop = MPI_Wtime(); time = tstop - tstart; if (rank == 0) { printf("Overall run time was %f seconds\n", time); } MPI_Finalize(); }
int main() { MPI_Init(NULL, NULL); /* MPI variables (in some sense) */ MPI_Comm comm; MPI_Status status; MPI_Request request; int size, rank, tag; int comm2d, disp, left, right, up, down, reorder; int dims[NDIMS], period[NDIMS], direction[NDIMS]; /* variable for the program */ int nx, ny, nxp, nyp, nxpe, nype; int i, j, iter; int lastcheck, checkinc; double max, delta; double avg, mean; char picName[20] = "edgeCHANGETHIS.pgm"; /* * find the size of the image do the arrays can be defined */ pgmsize(picName, &nx, &ny); comm = MPI_COMM_WORLD; MPI_Comm_size(comm, &size); tag = 1; /* Introduce Cartesian topology */ for(i=0; i<NDIMS; ++i) { dims[i] = 0; period[i] = FALSE; /* TRUE gives Cyclic */ direction[i] = i; /* shift along the same index as element of the array*/ } reorder = TRUE; /* allows the processes to become reordered to hopefully improve efficiency */ disp = 1; /* Shift by 1 */ MPI_Dims_create(size,NDIMS,dims); MPI_Cart_create(comm,NDIMS,dims,period,reorder,&comm2d); MPI_Comm_rank(comm2d,&rank); MPI_Cart_shift(comm2d,direction[1],disp,&left,&right); MPI_Cart_shift(comm2d,direction[0],disp,&up,&down); /* check the array is a reasonable size to be split up among the processors to be used and if not quit */ if(nx < dims[1] || ny < dims[0]) { if(ROOT == rank) { printf("too many processors running on job, %d in x direction but only %d elements, %d in y, %d elements\n", dims[1], nx, dims[0], ny); } return 1; } initialise_local_array_sizes(nx, ny, &nxp, &nyp, &nxpe, &nype, dims, rank, size); /* now declare the arrays necessary (note they can be different sizes on different processes*/ float localBuf[nxp][nyp]; float localEdge[nxp+2][nyp+2], localOld[nxp+2][nyp+2], localNew[nxp+2][nyp+2]; float globalImage[nx][ny]; /* * set the halos of all the appropriate arrays to 255 */ set_halos(localEdge,localOld, localNew, nxp, nyp); if(ROOT == rank) { printf("Reading in Picture\n"); pgmread(picName, globalImage, nx, ny); } /*set up all the datatypes that will need to be used*/ /*send contiguous halos*/ MPI_Datatype mcols; MPI_Type_contiguous(nyp, MPI_FLOAT, &mcols); MPI_Type_commit(&mcols); /*send non-conmtiguous halos*/ MPI_Datatype mrows; MPI_Type_vector(nxp, 1, nyp+2, MPI_FLOAT, &mrows); /*nyp+2 since will be used on nyp+2 size arrays*/ MPI_Type_commit(&mrows); /*scatter data to processes with same size arrays as ROOT*/ MPI_Datatype scatter[4]; MPI_Type_vector(nxp, nyp, ny, MPI_FLOAT, &scatter[3]); MPI_Type_commit(&scatter[3]); /*scatter data to processes with different size arrays than ROOT in dim[0]*/ MPI_Type_vector(nxp, nype, ny, MPI_FLOAT, &scatter[0]); MPI_Type_commit(&scatter[0]); /*scatter data to processes with different size arrays than ROOT in dim[1]*/ MPI_Type_vector(nxpe, nyp, ny, MPI_FLOAT, &scatter[1]); MPI_Type_commit(&scatter[1]); /*scatter data to processes with different size arrays than ROOT in dim[0] and dim[1]*/ MPI_Type_vector(nxpe, nype, ny, MPI_FLOAT, &scatter[4]); MPI_Type_commit(&scatter[4]); /* Scatter the data from processer 0 to the rest */ if(ROOT == rank) { printf("Scattering image\n"); scatter_data(globalImage, localBuf, ny, nxp, nyp, dims, rank, comm2d, scatter); } else { MPI_Recv(localBuf, nxp*nyp, MPI_FLOAT, 0, rank, comm2d, &status); } /* * set up the edge data to be used in computation */ for(i=0; i<nxp; ++i) { for(j=0; j<nyp; ++j) { localEdge[i+1][j+1] = localBuf[i][j]; localOld[i+1][j+1] = 255; } } /* * computation loop */ if(ROOT == rank) { printf("Performing update routine for %d iterations\n", ITERATIONS); } double t1, t2; t1 = MPI_Wtime(); tag = 2; lastcheck = checkinc = iter = 0; delta = 1; while(iter < ITERATIONS) { send_halos(localOld, left, right, up, down, comm2d, tag, nxp, nyp, mrows, mcols); avg = 0; for(i=1; i<nxp+1; ++i) { for(j=1; j<nyp+1; ++j) { localNew[i][j] = 0.25*(localOld[i-1][j] + localOld[i+1][j] + localOld[i][j-1] + localOld[i][j+1] - localEdge[i][j]); avg = avg + localNew[i][j]; } } max = 0; for(i=1; i<nxp+1; ++i) { for(j=1; j<nyp+1; ++j) { if(fabs(localNew[i][j] - localOld[i][j]) > max) { max = fabs(localNew[i][j] - localOld[i][j]); } localOld[i][j] = localNew[i][j]; } } /* * want to perform a calculation of the average pixel value and delta */ if(iter == lastcheck + checkinc) { lastcheck = iter; MPI_Reduce(&avg, &mean, 1, MPI_DOUBLE, MPI_SUM, ROOT, comm2d); MPI_Allreduce(&max, &delta, 1, MPI_DOUBLE, MPI_MAX, comm2d); if(ROOT == rank) { // printf("iteration %d, average pixel value is %f, current delta %f\n", iter, mean/(nx*ny), delta); } checkinc = (int)(delta*500); if(checkinc > 200) checkinc = 500; } ++iter; if(ITERATIONS == iter) { break; } } t2 = MPI_Wtime(); if(ROOT == rank) { printf("finished after %d iterations, delta was %f\n", iter-1, delta); printf("seconds per iteration: %f\n", (t2-t1)/(iter-1)); } for(i=0; i<nxp; ++i) { for(j=0; j<nyp; ++j) { localBuf[i][j] = localOld[i+1][j+1]; } } tag = 3; if(ROOT == rank) { printf("recieving back data\n"); receive_data(globalImage, localBuf, ny, nxp, nyp, dims, tag, rank, comm2d, scatter); } else { MPI_Issend(localBuf, nxp*nyp, MPI_FLOAT, ROOT, tag, comm2d, &request); MPI_Wait(&request, &status); } if(ROOT == rank) { pgmwrite("parpictureCHANGETHIS.pgm", globalImage, nx, ny); } MPI_Finalize(); return 0; }
int main() { int nx, ny, i, j, iter; int lastcheck, checkinc; double max; double avg; char picName[20] = "edge512x384.pgm"; /* * test that the image to be worked on is the right size for the nx and ny defined */ pgmsize(picName, &nx, &ny); float globalImage[nx][ny], localEdge[nx+2][ny+2], localOld[nx+2][ny+2], localNew[nx+2][ny+2]; /* * set the halos of all the appropriate arrays to 255 */ for(i=0; i<nx+2; ++i) { localEdge[i][0] = localEdge[i][ny+1] = 255; localOld[i][0] = localOld[i][ny+1] = 255; localNew[i][0] = localNew[i][ny+1] = 255; } for(j=0; j<ny+2; ++j) { localEdge[0][j] = localEdge[nx+1][j] = 255; localOld[0][j] = localOld[nx+1][j] = 255; localNew[0][j] = localNew[nx+1][j] = 255; } printf("Reading in Picture\n"); pgmread(picName, globalImage, nx, ny); /* * set up the edge data to be used in computation */ for(i=1; i<nx+1; ++i) { for(j=1; j<ny+1; ++j) { localEdge[i][j] = globalImage[i-1][j-1]; localOld[i][j] = 255; } } /* * computation loop */ printf("Performing update routine for %d iterations\n", ITERATIONS); lastcheck = checkinc = iter = 0; max = 1; while(max > 0.1) { avg = 0; for(i=1; i<nx+1; ++i) { for(j=1; j<ny+1; ++j) { localNew[i][j] = 0.25*(localOld[i-1][j] + localOld[i+1][j] + localOld[i][j-1] + localOld[i][j+1] - localEdge[i][j]); avg = avg + localNew[i][j]; } } if(iter == lastcheck + checkinc) max = 0; for(i=1; i<nx+1; ++i) { for(j=1; j<ny+1; ++j) { if(fabs(localNew[i][j] - localOld[i][j]) > max && iter == lastcheck + checkinc) { max = fabs(localNew[i][j] - localOld[i][j]); } localOld[i][j] = localNew[i][j]; } } /* * want to perform a calculation of the average pixel value and delta */ if(iter == lastcheck + checkinc) { lastcheck = iter; printf("iteration %d, average pixel value is %f, current delta: %f\n", iter, avg/(nx*ny), max); checkinc = (int)(max*500); if(checkinc > 200) checkinc = 500; } ++iter; if(ITERATIONS == iter) { break; } } printf("finished after %d iterations. Delta was %f\n", iter-1, max); /* * set the data back for printing */ for(i=0; i<nx; ++i) { for(j=0; j<ny; ++j) { globalImage[i][j] = localNew[i+1][j+1]; } } pgmwrite("picture.pgm", globalImage, nx, ny); return 0; }
/** * @brief Get the dimensions of an image (Wrapper for pgmsize) * @param filename the file to find the dimensions of * @param nx pointer to store the x dimension * @param ny pointer to store the y dimension */ void image_size (char *filename, int *nx, int *ny) { pgmsize(filename, nx, ny); }