Esempio n. 1
0
		super& operator/= (const super& other)
		{
            divide_rows(*this, other);
			return *this;
		}
Esempio n. 2
0
		super& operator/= (const virtual_recursator<value_type, false>& other)
		{
            divide_rows(*this, other);
			return *this;
		}
int main(int argc, char** argv) {
	int thread_count = 4;
	int fd, i, j, k, width, height, loops, t, row_div, col_div, rows, cols;
	double timer, remote_time;
	char *image;
	color_t imageType;
	/* MPI world topology */
    int process_id, num_processes;
	/* Find current task id */
    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &num_processes);
    MPI_Comm_rank(MPI_COMM_WORLD, &process_id);
	/* MPI status */
    MPI_Status status;
	/* MPI data types */
    MPI_Datatype grey_col_type;
    MPI_Datatype rgb_col_type;
    MPI_Datatype grey_row_type;
    MPI_Datatype rgb_row_type;
	/* MPI requests */
    MPI_Request send_north_req;
    MPI_Request send_south_req;
    MPI_Request send_west_req;
    MPI_Request send_east_req;
    MPI_Request recv_north_req;
    MPI_Request recv_south_req;
    MPI_Request recv_west_req;
    MPI_Request recv_east_req;
	
	/* Neighbours */
	int north = -1;
	int south = -1;
    int west = -1;
    int east = -1;

    /* Check arguments */
    if (process_id == 0) {
		Usage(argc, argv, &image, &width, &height, &loops, &imageType);
		/* Division of data in each process */
		row_div = divide_rows(height, width, num_processes);
		if (row_div <= 0 || height % row_div || num_processes % row_div || width % (col_div = num_processes / row_div)) {
				fprintf(stderr, "%s: Cannot divide to processes\n", argv[0]);
				MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
				return EXIT_FAILURE;
		}
	}
	if (process_id != 0) {
		image = malloc((strlen(argv[1])+1) * sizeof(char));
		strcpy(image, argv[1]);
	}
	/* Broadcast parameters */
    MPI_Bcast(&width, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Bcast(&height, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Bcast(&loops, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Bcast(&imageType, 1, MPI_INT, 0, MPI_COMM_WORLD);
	MPI_Bcast(&row_div, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Bcast(&col_div, 1, MPI_INT, 0, MPI_COMM_WORLD);
	
	/* Compute number of rows per process */
	rows = height / row_div;
	cols = width / col_div;

	/* Create column data type for grey & rgb */
	MPI_Type_vector(rows, 1, cols+2, MPI_BYTE, &grey_col_type);
	MPI_Type_commit(&grey_col_type);
	MPI_Type_vector(rows, 3, 3*cols+6, MPI_BYTE, &rgb_col_type);
	MPI_Type_commit(&rgb_col_type);
	/* Create row data type */
	MPI_Type_contiguous(cols, MPI_BYTE, &grey_row_type);
	MPI_Type_commit(&grey_row_type);
	MPI_Type_contiguous(3*cols, MPI_BYTE, &rgb_row_type);
	MPI_Type_commit(&rgb_row_type);

	 /* Compute starting row and column */
    int start_row = (process_id / col_div) * rows;
    int start_col = (process_id % col_div) * cols;
	
	/* Init filters */
	int box_blur[3][3] = {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}};
	int gaussian_blur[3][3] = {{1, 2, 1}, {2, 4, 2}, {1, 2, 1}};
	int edge_detection[3][3] = {{1, 4, 1}, {4, 8, 4}, {1, 4, 1}};
	float **h = malloc(3 * sizeof(float *));
	for (i = 0 ; i < 3 ; i++)
		h[i] = malloc(3 * sizeof(float));
	for (i = 0 ; i < 3 ; i++) {
		for (j = 0 ; j < 3 ; j++){
			// h[i][j] = box_blur[i][j] / 9.0;
			h[i][j] = gaussian_blur[i][j] / 16.0;
			// h[i][j] = edge_detection[i][j] / 28.0;
		}
	}

	/* Init arrays */
	uint8_t *src = NULL, *dst = NULL, *tmpbuf = NULL, *tmp = NULL;
	MPI_File fh;
	int filesize, bufsize, nbytes;
	if (imageType == GREY) {
		filesize = width * height;
		bufsize = filesize / num_processes;
		nbytes = bufsize / sizeof(uint8_t);
		src = calloc((rows+2) * (cols+2), sizeof(uint8_t));
		dst = calloc((rows+2) * (cols+2), sizeof(uint8_t));
	} else if (imageType == RGB) {
		filesize = width*3 * height;
		bufsize = filesize / num_processes;
		nbytes = bufsize / sizeof(uint8_t);
		src = calloc((rows+2) * (cols*3+6), sizeof(uint8_t));
		dst = calloc((rows+2) * (cols*3+6), sizeof(uint8_t));
	}
	if (src == NULL || dst == NULL) {
        fprintf(stderr, "%s: Not enough memory\n", argv[0]);
        MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
        return EXIT_FAILURE;
	}

	/* Parallel read */
	MPI_File_open(MPI_COMM_WORLD, image, MPI_MODE_RDONLY, MPI_INFO_NULL, &fh);
	if (imageType == GREY) {
		for (i = 1 ; i <= rows ; i++) {
			MPI_File_seek(fh, (start_row + i-1) * width + start_col, MPI_SEEK_SET);
			tmpbuf = offset(src, i, 1, cols+2);
			MPI_File_read(fh, tmpbuf, cols, MPI_BYTE, &status);
		}
	} else if (imageType == RGB) {
		for (i = 1 ; i <= rows ; i++) {
			MPI_File_seek(fh, 3*(start_row + i-1) * width + 3*start_col, MPI_SEEK_SET);
			tmpbuf = offset(src, i, 3, cols*3+6);
			MPI_File_read(fh, tmpbuf, cols*3, MPI_BYTE, &status);
		}
	}
	MPI_File_close(&fh);

	/* Compute neighbours */
    if (start_row != 0)
        north = process_id - col_div;
    if (start_row + rows != height)
        south = process_id + col_div;
    if (start_col != 0)
        west = process_id - 1;
    if (start_col + cols != width)
        east = process_id + 1;
	
	/* Get time before */
    timer = MPI_Wtime();
	/* Convolute "loops" times */
	for (t = 0 ; t < loops ; t++) {
        /* Send and request borders */
		if (imageType == GREY) {
			if (north != -1) {
				MPI_Isend(offset(src, 1, 1, cols+2), 1, grey_row_type, north, 0, MPI_COMM_WORLD, &send_north_req);
				MPI_Irecv(offset(src, 0, 1, cols+2), 1, grey_row_type, north, 0, MPI_COMM_WORLD, &recv_north_req);
			}
			if (west != -1) {
				MPI_Isend(offset(src, 1, 1, cols+2), 1, grey_col_type,  west, 0, MPI_COMM_WORLD, &send_west_req);
				MPI_Irecv(offset(src, 1, 0, cols+2), 1, grey_col_type,  west, 0, MPI_COMM_WORLD, &recv_west_req);
			}
			if (south != -1) {
				MPI_Isend(offset(src, rows, 1, cols+2), 1, grey_row_type, south, 0, MPI_COMM_WORLD, &send_south_req);
				MPI_Irecv(offset(src, rows+1, 1, cols+2), 1, grey_row_type, south, 0, MPI_COMM_WORLD, &recv_south_req);
			}
			if (east != -1) {
				MPI_Isend(offset(src, 1, cols, cols+2), 1, grey_col_type,  east, 0, MPI_COMM_WORLD, &send_east_req);
				MPI_Irecv(offset(src, 1, cols+1, cols+2), 1, grey_col_type,  east, 0, MPI_COMM_WORLD, &recv_east_req);
			}
		} else if (imageType == RGB) {
			if (north != -1) {
				MPI_Isend(offset(src, 1, 3, 3*cols+6), 1, rgb_row_type, north, 0, MPI_COMM_WORLD, &send_north_req);
				MPI_Irecv(offset(src, 0, 3, 3*cols+6), 1, rgb_row_type, north, 0, MPI_COMM_WORLD, &recv_north_req);
			}
			if (west != -1) {
				MPI_Isend(offset(src, 1, 3, 3*cols+6), 1, rgb_col_type,  west, 0, MPI_COMM_WORLD, &send_west_req);
				MPI_Irecv(offset(src, 1, 0, 3*cols+6), 1, rgb_col_type,  west, 0, MPI_COMM_WORLD, &recv_west_req);
			}
			if (south != -1) {
				MPI_Isend(offset(src, rows, 3, 3*cols+6), 1, rgb_row_type, south, 0, MPI_COMM_WORLD, &send_south_req);
				MPI_Irecv(offset(src, rows+1, 3, 3*cols+6), 1, rgb_row_type, south, 0, MPI_COMM_WORLD, &recv_south_req);
			}
			if (east != -1) {
				MPI_Isend(offset(src, 1, 3*cols, 3*cols+6), 1, rgb_col_type,  east, 0, MPI_COMM_WORLD, &send_east_req);
				MPI_Irecv(offset(src, 1, 3*cols+3, 3*cols+6), 1, rgb_col_type,  east, 0, MPI_COMM_WORLD, &recv_east_req);
			}
		}

		/* Inner Data Convolute */
		convolute(src, dst, 1, rows, 1, cols, cols, rows, h, imageType);

	    /* Request and compute */
		if (north != -1) {
			MPI_Wait(&recv_north_req, &status);
			
			convolute(src, dst, 1, 1, 2, cols-1, cols, rows, h, imageType);
		}
		if (west != -1) {
			MPI_Wait(&recv_west_req, &status);
			convolute(src, dst, 2, rows-1, 1, 1, cols, rows, h, imageType);
		}
		if (south != -1) {
			MPI_Wait(&recv_south_req, &status);
			convolute(src, dst, rows, rows, 2, cols-1, cols, rows, h, imageType);
		}
		if (east != -1) {
			MPI_Wait(&recv_east_req, &status);
			convolute(src, dst, 2, rows-1, cols, cols, cols, rows, h, imageType);
		}

		/* Corner data */
		if (north != -1 && west != -1)
			convolute(src, dst, 1, 1, 1, 1, cols, rows, h, imageType);
		if (west != -1 && south != -1)
			convolute(src, dst, rows, rows, 1, 1, cols, rows, h, imageType);
		if (south != -1 && east != -1)
			convolute(src, dst, rows, rows, cols, cols, cols, rows, h, imageType);
		if (east != -1 && north != -1)
			convolute(src, dst, 1, 1, cols, cols, cols, rows, h, imageType);

		/* Wait to have sent all borders */
		if (north != -1)
			MPI_Wait(&send_north_req, &status);
		if (west != -1)
			MPI_Wait(&send_west_req, &status);
		if (south != -1)
			MPI_Wait(&send_south_req, &status);
		if (east != -1)
			MPI_Wait(&send_east_req, &status);

		/* swap arrays */
		tmp = src;
	    src = dst;
	    dst = tmp;
	}
	/* Get time elapsed */
    timer = MPI_Wtime() - timer;

	/* Parallel write */
	char *outImage = malloc((strlen(image) + 9) * sizeof(char));
	strcpy(outImage, "blur_");
	strcat(outImage, image);
	MPI_File outFile;
	MPI_File_open(MPI_COMM_WORLD, outImage, MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &outFile);
	if (imageType == GREY) {
		for (i = 1 ; i <= rows ; i++) {
			MPI_File_seek(outFile, (start_row + i-1) * width + start_col, MPI_SEEK_SET);
			tmpbuf = offset(src, i, 1, cols+2);
			MPI_File_write(outFile, tmpbuf, cols, MPI_BYTE, MPI_STATUS_IGNORE);
		}
	} else if (imageType == RGB) {
		for (i = 1 ; i <= rows ; i++) {
			MPI_File_seek(outFile, 3*(start_row + i-1) * width + 3*start_col, MPI_SEEK_SET);
			tmpbuf = offset(src, i, 3, cols*3+6);
			MPI_File_write(outFile, tmpbuf, cols*3, MPI_BYTE, MPI_STATUS_IGNORE);
		}
	}
	MPI_File_close(&outFile);

	/* Get times from other processes and print maximum */
    if (process_id != 0)
        MPI_Send(&timer, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
    else {
        for (i = 1 ; i != num_processes ; ++i) {
            MPI_Recv(&remote_time, 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &status);
            if (remote_time > timer)
                timer = remote_time;
        }
        printf("%f\n", timer);
    }

    /* De-allocate space */
    free(src);
    free(dst);
    MPI_Type_free(&rgb_col_type);
    MPI_Type_free(&rgb_row_type);
    MPI_Type_free(&grey_col_type);
    MPI_Type_free(&grey_row_type);

	/* Finalize and exit */
    MPI_Finalize();
	return EXIT_SUCCESS;
}