Ejemplo n.º 1
0
/**
 * Creates a matrix from an input stream. Returns data as an array of rows.
 * Caller responsible for freeing returned structure.
 */
Matrix* create_matrix(FILE *in) {
    Matrix *m = NULL;
    int rows = 0;
    int columns = 0;

    if (!at_valid_matrix(in)) goto MatrixMalformedError;
    if (!read_dims(in, &rows, &columns)) {
        goto MatrixDimError;
    }
    m = new_matrix(rows, columns);
    int i = 0;
    for (i = 0; i < m->rows; ++i) {
        if (!read_row(in, m->data[i], m->columns)) {
            goto MatrixEntryError;
        }
    }
    return m;
    // evil gotos for exception handling
MatrixMalformedError:
    printf("The input.dat file appears corrupt, are you sure it's the proper format?\n");
    goto FreeAndReturn;
MatrixDimError:
    printf("Matrix dimension data corrupt\n");
    goto FreeAndReturn;
MatrixEntryError:
    printf("Matrix data corrupt\n");
    goto FreeAndReturn;
FreeAndReturn:
    free_matrix(&m);
    return NULL;
}
Ejemplo n.º 2
0
/*
 main entry point to program.  Determines number of tasks, the 0 task becomes
 the head, reading the data and broadcasting it to all other tasks which act
 as workers.  The 0 task then computes its portion of the result and then
 receives the results from all workers.  The result is then printed.
 */
int main(int argc, char *argv[]) {
  int i, head, lo, hi, me, tasks;
  int a_rows, a_cols, a_cells, b_rows, b_cols, b_cells;
  int *recv_cnts, *disps;
  int *datapack, *temp;
  FILE *fp;

  MPI_Status status;

  /* init MPI, retrieve number of tasks, retrieve my index in tasks */
  MPI_Init(&argc, &argv);
  MPI_Comm_size(MPI_COMM_WORLD, &tasks);
  MPI_Comm_rank(MPI_COMM_WORLD, &me);

  /* first task is head, collecting results */
  head = 0;

  /* check for input file parameter */
  if (argc < 2) {
    if (me == head)
      BAIL_ALL("Please provide an input parameter");
  }

  if (me == head ) {

    /* create arrays for receive counts and displacements for MPI_Gatherv */
    if ((recv_cnts = (int *)malloc(tasks*sizeof(int))) == NULL)
      BAIL_ALL("Unable to allocate receive counts array");
    if ((disps = (int *)malloc(tasks*sizeof(int))) == NULL)
      BAIL_ALL("Unable to allocate displacements arrary");

    /* attempt to open the input file */
    if ((fp = fopen(argv[1], "r")) == NULL)
      BAIL_ALL("Unable to open the input file");

    while (!feof(fp)) {

      /* read the dimensions of matrix A */
      if (!read_dims(fp, &a_rows, &a_cols))
        BAIL_ALL("Unable to read the dimensions of matrix A");

      a_cells = a_rows * a_cols;

      /* allocate the space for the dimensions and matrix A */
      if ((datapack = (int *)malloc((2+a_cells)*sizeof(int))) == NULL)
        BAIL_ALL("Unable to allocate space for matrix A");

      /* put row and column data in the datapack */
      datapack[0] = a_rows;
      datapack[1] = a_cols;

      /* attempt to read in the matrix A values */
      if (read_matrix(fp, datapack+2, a_cells) < a_cells)
        BAIL_ALL("Unable to read the contents of matrix A");

      /* read the dimensions of matrix B */
      if (!read_dims(fp, &b_rows, &b_cols))
        BAIL_ALL("Unable to read the dimensions of matrix B");

      b_cells = b_rows * b_cols;

      /* allocate the extra space for dimensions and matrix B */
      if ((datapack = (int *)realloc(datapack,
                                     (4+a_cells+b_cells)*sizeof(int))) == NULL)
        BAIL_ALL("Unable to allocate space for matrix B");

      /* put row and column data in the datapack */
      datapack[2 + a_cells] = b_rows;
      datapack[3 + a_cells] = b_cols;

      /* attempt to read in the matrix B values */
      if (read_matrix(fp, datapack+4+a_cells, b_cells) < b_cells)
        BAIL_ALL("Unable to read the contents of matrix B");

      /* check for multiplication compatibility */
      if (a_cols != b_rows ||
          a_rows < 1 || a_cols < 1 ||
          b_rows < 1 || b_cols < 1) {
        printf("Matrix A and B are not multiplicative compatible\n");
      } else {
        /* calc the range of cells I am responsible for */
        calc_range(a_rows*b_cols, me, tasks, &lo, &hi);

        /* allocate an array for the portion I will compute */
        if ((temp = (int *)malloc((hi-lo+1)*sizeof(int))) == NULL)
          BAIL_ALL("Unable to allocate space for the temp array");

        /* tell the workers the size of the datapack coming in */
        i = 4 + a_cells + b_cells;
        MPI_Bcast(&i, 1, MPI_INT, me, MPI_COMM_WORLD);

        /* send the datapack to the workers */
        MPI_Bcast(datapack, 4+a_cells+b_cells, MPI_INT, me, MPI_COMM_WORLD);

        /* calculate my portion of the results */
        for (i=lo; i<=hi; i++) {
          temp[i-lo] = calc_cell(datapack+2, datapack+4+a_cells, a_cols,
                                 a_rows, b_cols, i);
        }

        /* calculate the proper displacements and sizes for returned results */
        for (i=0; i<tasks; i++) {
          int worker_hi;
          calc_range(a_rows*b_cols, i, tasks, disps+i, &worker_hi);
          recv_cnts[i] = worker_hi - disps[i] + 1;
        }

        /* print out the matrices */
        printf("MATRIX A\n");
        print_matrix(datapack+2, a_rows, a_cols);
        printf("MATRIX B\n");
        print_matrix(datapack+4+a_cells, b_rows, b_cols);

        /* gatherv the results */
        MPI_Gatherv(temp, hi-lo+1, MPI_INT, datapack, recv_cnts, disps,
                    MPI_INT, me, MPI_COMM_WORLD);

        /* print out the result */
        printf("RESULT\n");
        print_matrix(datapack, a_rows, b_cols);

        free(temp);

      }

      free(datapack);

    }

  } else { /* not the head task */

    for (;;) {

      /* check if more results are coming */
      MPI_Bcast(&i, 1, MPI_INT, head, MPI_COMM_WORLD);
      if (!i) break;

      /* allocate space for the data pack */
      datapack = (int *)malloc(i*sizeof(int));

      /* receive the datapack */
      MPI_Bcast(datapack, i, MPI_INT, head, MPI_COMM_WORLD);

      /* get values from the data pack */
      a_rows = datapack[0];
      a_cols = datapack[1];
      a_cells = a_rows*a_cols;
      b_rows = datapack[2 + a_cells];
      b_cols = datapack[3 + a_cells];
      b_cells = b_rows*b_cols;

      /* calculate the range of cells that I am responsible for */
      calc_range(a_rows*b_cols, me, tasks, &lo, &hi);

      /* allocate an array for the results I will send back */
      temp = (int *)malloc((hi-lo+1)*sizeof(int));

      /* and calculate my set of results */
      for (i=lo; i<=hi; i++) {
        temp[i-lo] = calc_cell(datapack+2, datapack+4+a_cells, a_cols, a_rows,
                               b_cols, i);
      }

      /* return the values to the head task */
      MPI_Gatherv(temp, hi-lo+1, MPI_INT, NULL, NULL, NULL, MPI_INT, head,
                  MPI_COMM_WORLD);

      free(datapack);
      free(temp);

    }

  }

  if (me == head) {
    fclose(fp);
    BAIL_ALL("Job complete!");
  }

  /* shut down */
  MPI_Finalize();
  exit(0);

}