void * blurfilterwrapper(void * arg){ blurfilterdata * data = (blurfilterdata*) arg; blurfilter(data->xsize, data->ysize, data->src, data->dst, data->radius, data->w, data->imageThreads, data->rank); return NULL; }
int main (int argc, char ** argv) { int radius; int xsize, ysize, colmax; pixel src[MAX_PIXELS]; struct timespec stime, etime; #define MAX_RAD 1000 int np, me; double w[MAX_RAD]; MPI_Init( &argc, &argv ); MPI_Comm_size( MPI_COMM_WORLD, &np ); MPI_Comm_rank( MPI_COMM_WORLD, &me ); /* Take care of the arguments */ if(me == MASTER){ if (argc != 4) { fprintf(stderr, "Usage: %s radius infile outfile\n", argv[0]); exit(1); } radius = atoi(argv[1]); if((radius > MAX_RAD) || (radius < 1)) { fprintf(stderr, "Radius (%d) must be greater than zero and less then %d\n", radius, MAX_RAD); exit(1); } /* read file */ if(read_ppm (argv[2], &xsize, &ysize, &colmax, (char *) src) != 0) exit(1); if (colmax > 255) { fprintf(stderr, "Too large maximum color-component value\n"); exit(1); } /* filter */ get_gauss_weights(radius, w); printf("Has read the image and generated Coefficients\n"); } // radius, common to everybody MPI_Bcast( &radius, 1, MPI_INT, 0, MPI_COMM_WORLD ); // w, common to everybody MPI_Bcast( w, MAX_RAD, MPI_DOUBLE, 0, MPI_COMM_WORLD ); //xsize, common to everybody MPI_Bcast( &xsize, 1, MPI_INT, 0, MPI_COMM_WORLD ); //ysize, common to everybody MPI_Bcast( &ysize, 1, MPI_INT, 0, MPI_COMM_WORLD ); /* create a datatype for struct pixel */ const int nitems=3; int blocklengths[3] = {1,1,1}; MPI_Datatype types[3] = {MPI_UNSIGNED_CHAR, MPI_UNSIGNED_CHAR, MPI_UNSIGNED_CHAR}; MPI_Datatype mpi_pixel_type; MPI_Aint offsets[3]; offsets[0] = 0; offsets[1] = 1; offsets[2] = 2; MPI_Type_create_struct(nitems, blocklengths, offsets, types, &mpi_pixel_type); MPI_Type_commit(&mpi_pixel_type); /* calculate areas to be computed by each processor */ int * sendcounts; int * displace; int * recvcounts; int * recvdisplace; int * rag; sendcounts = malloc(sizeof(int)*np); recvcounts = malloc(sizeof(int)*np); displace = malloc(sizeof(int)*np); recvdisplace = malloc(sizeof(int)*np); int original_radius; int line, rem, sum; sum= 0; rem = ysize % np; // calculate send counts and displacements int i; int pointer[np]; if(np>1){ line = (ysize/np); original_radius = radius; for (i = 0; i < np; i++) { radius = original_radius; displace[i] = sum; recvdisplace[i] = displace[i]; int line_rem = 0; if (rem > 0) { line_rem++; rem--; } line_rem+=line; recvcounts[i] = line_rem; if(i == 0){ if(displace[i]/xsize + line_rem + radius > ysize){ radius = ysize - (displace[i]/xsize + line_rem); } sendcounts[i] = line_rem+radius; pointer[0] = 0; }else if(i == np-1){ if(displace[i]/xsize - radius < 0){ radius = displace[i]/xsize; } sendcounts[i] = line_rem + radius; displace[i] -= (radius*xsize); pointer[i] = radius*xsize; }else if(i>0 && i<np-1){ if(0 + displace[i]/xsize-radius < 0){ radius = displace[i]/xsize - 0; } sendcounts[i] = line_rem + radius; int sofar = displace[i]/xsize; displace[i] -= (radius*xsize); pointer[i] = radius*xsize; radius = original_radius; if(sofar + line_rem + radius > ysize){ radius = ysize - (sofar + line_rem); } sendcounts[i] += radius; } sum += line_rem*xsize; sendcounts[i] *= xsize; recvcounts[i] *= xsize; if(me == MASTER) printf("Process %d. \t Area to compute: %d . \t starting from: %d \t Displ recv: %d\n\n ", i, sendcounts[i], (displace[i]/xsize),(recvdisplace[i]/xsize)); } }else{ sendcounts[0] = xsize*ysize; recvcounts[0] = xsize*ysize; displace[0] = 0; recvdisplace[0] = 0; pointer[0] = 0; rag[0] = ysize; } pixel buffer_receiver[sendcounts[me]]; MPI_Scatterv( &src, sendcounts , displace, mpi_pixel_type , &buffer_receiver, sendcounts[me], mpi_pixel_type , 0, MPI_COMM_WORLD ); clock_gettime(CLOCK_REALTIME, &stime); blurfilter(xsize, sendcounts[me]/xsize, buffer_receiver, original_radius, w); pixel * p ; p= &buffer_receiver[pointer[me]]; MPI_Gatherv ( p, recvcounts[me], mpi_pixel_type, &src, recvcounts, recvdisplace, mpi_pixel_type, 0 , MPI_COMM_WORLD); clock_gettime(CLOCK_REALTIME, &etime); char filename[5]; sprintf(filename, "file%d.ppm", me); if(me == MASTER){ printf("Main Master Filtering took: %g secs\n", (etime.tv_sec - stime.tv_sec) + 1e-9*(etime.tv_nsec - stime.tv_nsec)) ; /* write result */ printf("Writing output file\n"); if(write_ppm (argv[3], xsize, ysize, (char *)src) != 0) exit(1); printf("Image written on %s\n",argv[3]); }else{ if (write_ppm (filename, xsize, recvcounts[me]/xsize, (char *)&buffer_receiver[pointer[me]]) != 0) exit(1); } MPI_Finalize(); return(0); }
int main (int argc, char ** argv) { int taskid, ntasks; int xsize, ysize, colmax; pixel src[MAX_PIXELS]; double w[MAX_RAD]; struct timespec stime, etime; struct timespec tstime, tetime; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &taskid); MPI_Comm_size(MPI_COMM_WORLD, &ntasks); // Create a custom MPI datatype for pixel pixel item; MPI_Datatype pixel_mpi; MPI_Datatype type[3] = { MPI_UNSIGNED_CHAR, MPI_UNSIGNED_CHAR, MPI_UNSIGNED_CHAR }; int blocklen[] = { 1, 1, 1 }; MPI_Aint start, disp[3]; MPI_Address( &item, &start ); MPI_Address( &item.r, &disp[0] ); MPI_Address( &item.g, &disp[1] ); MPI_Address( &item.b, &disp[2] ); disp[0] -= start; disp[1] -= start; disp[2] -= start; MPI_Type_struct(3, blocklen, disp, type, &pixel_mpi); MPI_Type_commit(&pixel_mpi); int buffsize, radius, startY, endY; /* Take care of the arguments */ if (argc != 4) { fprintf(stderr, "Usage: %s radius infile outfile\n", argv[0]); exit(1); } radius = atoi(argv[1]); if((radius > MAX_RAD) || (radius < 1)) { fprintf(stderr, "Radius (%d) must be greater than zero and less then %d\n", radius, MAX_RAD); exit(1); } if (taskid == ROOT) { /* read file */ if(read_ppm (argv[2], &xsize, &ysize, &colmax, (char *) src) != 0) exit(1); if (colmax > 255) { fprintf(stderr, "Too large maximum color-component value\n"); exit(1); } /* filter */ printf("Has read the image, generating coefficients\n"); get_gauss_weights(radius, w); } // Broadcast the gaussian weight vector MPI_Bcast(w, MAX_RAD, MPI_DOUBLE, ROOT, MPI_COMM_WORLD); // Broadcast image dimensions MPI_Bcast(&xsize, 1, MPI_INT, ROOT, MPI_COMM_WORLD); MPI_Bcast(&ysize, 1, MPI_INT, ROOT, MPI_COMM_WORLD); // Calculate chunk size buffsize = ceil((float)ysize / (float)ntasks) * xsize; pixel recvbuff[MAX_PIXELS]; int sendcnts[ntasks], displs[ntasks], result_write_starts[ntasks], recievecounts[ntasks]; int i; // Generate sendcount and displacement vectors for Scatterv for (i = 0; i < ntasks; i++) { // Send enought neighbors to make it possible to also calculate // blur in the edges of the chunk sendcnts[i] = buffsize + 2 * radius * xsize; displs[i] = max(0, i * buffsize); } clock_gettime(CLOCK_REALTIME, &tstime); // Send the image in chunks to all nodes MPI_Scatterv(src, sendcnts, displs, pixel_mpi, recvbuff, buffsize + 2 * radius * xsize, pixel_mpi, ROOT, MPI_COMM_WORLD); clock_gettime(CLOCK_REALTIME, &stime); // Run the filter on the recieved chunk blurfilter(xsize, (ysize / ntasks) + 2 * radius, recvbuff, radius, w, taskid); clock_gettime(CLOCK_REALTIME, &etime); printf("Filtering at %i took: %g secs\n", taskid, (etime.tv_sec - stime.tv_sec) + 1e-9*(etime.tv_nsec - stime.tv_nsec)); // Generate sendcount and displacement vectors for Scatterv for (i = 0; i < ntasks; i++) { result_write_starts[i] = i * buffsize + xsize * radius; // Only send as much of the chunk that is really useful data recievecounts[i] = buffsize; } // Start writing from the beginning of the buffer if root result_write_starts[0] = 0; // Since the root node has no overlap in the beginning, we need to // send a little bit more from that node than from the rest. recievecounts[0] = buffsize + xsize * radius; pixel* result_read_start; if(taskid==ROOT) { // Root-node has no duplicated data in the beginning result_read_start = recvbuff; } else { // Jump over the duplicated data in the beginning of each chunk result_read_start = recvbuff + xsize * radius; } MPI_Gatherv(result_read_start, recievecounts[taskid], pixel_mpi, src, recievecounts, result_write_starts, pixel_mpi, ROOT, MPI_COMM_WORLD); clock_gettime(CLOCK_REALTIME, &tetime); MPI_Finalize(); /* write result */ if (taskid == ROOT) { printf("Everything took: %g secs\n", (tetime.tv_sec - tstime.tv_sec) + 1e-9*(tetime.tv_nsec - tstime.tv_nsec)); printf("Writing output file\n"); if(write_ppm (argv[3], xsize, ysize, (char *)src) != 0) exit(1); } return(0); }