int main (int argc, char ** argv) { int radius, ret; int xsize, ysize, colmax, i; struct timespec stime, etime; double w[MAX_RAD]; pixel *src = (pixel*) malloc(sizeof(pixel)*MAX_PIXELS); pixel *dst = (pixel*) malloc(sizeof(pixel)*MAX_PIXELS); /* Take care of the arguments */ if (argc != 5) { fprintf(stderr, "Usage: %s num_threads radius infile outfile\n", argv[0]); exit_prog(src, dst, 1); } int num_threads = atoi(argv[1]); radius = atoi(argv[2]); if((radius > MAX_RAD) || (radius < 1)) { fprintf(stderr, "Radius (%d) must be greater than zero and less then %d\n", radius, MAX_RAD); exit_prog(src, dst, 1); } /* read file */ if(read_ppm (argv[3], &xsize, &ysize, &colmax, (char *) src) != 0){ exit_prog(src, dst, 1); } if( num_threads < 1 || num_threads > ysize){ fprintf(stderr, "Number of threads needs to be bigger than 0 and smaller than ysize of image\n"); exit_prog(src, dst, 1); } if (colmax > 255) { fprintf(stderr, "Too large maximum color-component value\n"); exit_prog(src, dst, 1); } pthread_t threads[num_threads]; blur_data *pdata[num_threads]; int l_ysize = ysize/num_threads; // Calculate gauss weights get_gauss_weights(radius, w); printf("Calling filter\n"); clock_gettime(CLOCK_REALTIME, &stime); for(i=0;i<num_threads;i++){ pdata[i] = malloc(sizeof(blur_data)); pdata[i]->xsize = xsize; pdata[i]->ysize = l_ysize; if(i == num_threads - 1){ pdata[i]->ysize += ysize - l_ysize*num_threads; } pdata[i]->src = src + i*l_ysize*xsize; pdata[i]->dst = dst + i*l_ysize*xsize; pdata[i]->radius = radius; pdata[i]->w = w; // Number of rows above the threads part of the image pdata[i]->rows_up = i*l_ysize; // Number of rows below the threads part of the image pdata[i]->rows_down = ysize - l_ysize - pdata[i]->rows_up; ret = pthread_create(&threads[i], NULL, blurfilter_x, (void*)pdata[i]); if(ret){ fprintf(stderr, "ERROR creating thread\n"); free(pdata[i]); exit_prog(src, dst, 1); } } for(i=0;i<num_threads;i++){ pthread_join(threads[i], NULL); } for(i=0;i<num_threads;i++){ ret = pthread_create(&threads[i], NULL, blurfilter_y, (void*)pdata[i]); if(ret){ fprintf(stderr, "ERROR creating thread\n"); free(pdata[i]); exit_prog(src, dst, 1); } } for(i=0;i<num_threads;i++){ pthread_join(threads[i], NULL); } clock_gettime(CLOCK_REALTIME, &etime); printf("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[4], xsize, ysize, (char *)src) != 0){ exit_prog(src, dst, 1); } free(src); free(dst); return 0; }
int main (int argc, char ** argv) { int radius; int xsize, ysize, colmax, np, me; pixel * src = malloc (MAX_PIXELS * sizeof(pixel)); double w[MAX_RAD]; /* MPI INITIALIZATION */ 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"); } // BROADCASTING RADIUS MPI_Bcast( &radius, 1, MPI_INT, MASTER, MPI_COMM_WORLD ); // BROADCASTING W MPI_Bcast( w, MAX_RAD, MPI_DOUBLE, MASTER, MPI_COMM_WORLD ); // BROADCASTING XSIZE MPI_Bcast( &xsize, 1, MPI_INT, MASTER, MPI_COMM_WORLD ); // BROADCASTING YSIZE MPI_Bcast( &ysize, 1, MPI_INT, MASTER, MPI_COMM_WORLD ); /* MPI_DATATYPE : mpi_pixel_type */ 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); /* COMPUTE THE AREA TO BE EXECUTED BY EACH PROCESSOR*/ int * sendcounts, * displace; sendcounts = malloc(sizeof(int)*np); displace = malloc(sizeof(int)*np); int * line_starts = malloc (np * sizeof(int)), * line_ends = malloc (np * sizeof(int)), * line_send_starts = malloc (np * sizeof(int)), * line_send_ends = malloc (np * sizeof(int)), * sizes = malloc (np * sizeof(int)), * n_starts = malloc (np * sizeof(int)), * n_sizes = malloc (np * sizeof(int)); int line, rem, line_sum = 0; int i; line = ysize / np; rem = ysize % np; for (i = 0; i < np; i++) { sizes [i] = (rem > i) ? line + 1: line; line_starts [i] = line_sum; line_ends [i] = line_sum + sizes [i]; n_starts [i] = xsize * line_starts [i]; n_sizes [i] = xsize * sizes [i]; line_send_starts [i] = ((line_starts [i] - radius) < 0) ? 0 : line_starts [i] - radius; line_send_ends [i] = ((line_ends [i] + radius) > ysize) ? ysize : line_ends [i] + radius; sendcounts [i] = (line_send_ends [i] - line_send_starts [i]) * xsize; displace [i] = line_send_starts [i] * xsize; line_sum += sizes [i]; if (me == MASTER) { printf("P%d: starting from line %d to line %d (%d lines) and sending from line %d to %d (%d lines)\n", i, line_starts [i], line_ends[i], line_ends[i] - line_starts [i], line_send_starts[i], line_send_ends[i], line_send_ends[i] - line_send_starts[i]); } } pixel * buffer_receiver = malloc (sizeof(pixel) * sendcounts[me]); double start, end; start = MPI_Wtime(); /* DIVIDE THE IMAGE FOR THE COMPUTATION BY EACH PROCESSOR */ MPI_Scatterv( src, sendcounts , displace, mpi_pixel_type , buffer_receiver, sendcounts[me], mpi_pixel_type , MASTER, MPI_COMM_WORLD ); int local_ysize = line_send_ends [me] - line_send_starts [me], local_start = line_starts [me] - line_send_starts [me], local_end = local_start + sizes [me]; /* COMPUTE THE BLUR FILTER */ blurfilter_bordered(xsize, local_ysize, local_start, local_end, buffer_receiver, radius, w); /* GET THE PROCESSED SUBIMAGES AND MERGE THEM */ MPI_Gatherv (buffer_receiver + local_start * xsize, n_sizes [me], mpi_pixel_type, src, n_sizes, n_starts, mpi_pixel_type, MASTER , MPI_COMM_WORLD); end = MPI_Wtime()-start; if (me == MASTER){ //printf("Main Master Filtering took: %g sec, s\n", (etime.tv_sec - stime.tv_sec) + 1e-9*(etime.tv_nsec - stime.tv_nsec)) ; end = MPI_Wtime()-start; printf("MASTER mpi time: %g sec\n",end); //print the time on the file FILE * fp; char * f; f = "measures.csv"; fp = fopen(f, "a");// "w" means that we are going to write on this file, "a" appends fprintf(fp,"%g\n",end); // just write down the elapsed seconds: we'll make only copy&paste to the excel :) fclose(fp); /* 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]); } 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); }