Пример #1
0
int MPI_Gatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
                void *recvbuf, int *recvcounts, int *displs,
                MPI_Datatype recvtype, int root, MPI_Comm comm)
{
  return PMPI_Gatherv(sendbuf, sendcount, sendtype,
                      recvbuf, recvcounts, displs, recvtype,
                      root, comm);
}
Пример #2
0
int main(int argc, char **argv) {

    /* Validate arguments */
    if (argc != 5) {
        fprintf(stderr, "Usage: %s [input file] [output file] [grid size] [iterations]\n", argv[0]);
        return 1;
    }

    double t1 = MPI_Wtime();

    /* Initialize MPI */
    int tasks, rank;
    MPI_Init(NULL, NULL);
    MPI_Comm_size(MPI_COMM_WORLD, &tasks);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    double t_init = MPI_Wtime();

    /* Declare global variables */
    double *initial = NULL;
    int N = atoi(argv[3]);
    int T = atoi(argv[4]);

    /*****************************************************************/
    /* READ DATA                                                     */
    /*****************************************************************/
    if (rank == 0) {
        if (DEBUG) {
            fprintf(stderr, "\n-------------------------------------------\n");
            fprintf(stderr, "Starting heat.c with %d processes\n", tasks);
        }

        /* Read data */
        FILE *in = fopen(argv[1], "r");
        initial = malloc(N * N * sizeof(double));

        if (DEBUG) {
            for (int i = 1; i <= N; i++) {
                for (int j = 1; j <= N; j++) {
                    double val = (double) (i * (N - i - 1) * j * (N - j - 1));
                    initial[(i - 1) * N + (j - 1)] = val;
                }
            }
        } else {
            for (int i = 0; i < N * N; i++) {
                int x, y;
                double z;
                fscanf(in, "%d %d %lf\n", &x, &y, &z);
                initial[(x - 1) * N + (y - 1)] = z;
            }
        }

        fclose(in);
    }

    double t_read = MPI_Wtime();

    /*****************************************************************/
    /* DISTRIBUTE DATA                                               */
    /*****************************************************************/
    /* Preliminaries */
    int rowsPerWorker = N / tasks;
    int extra = N % tasks;

    /* Determine neighboring workers */
    int pred = rank - 1;
    int succ = rank + 1;

    /* Determine how many values each worker will get */
    int offset = 0;
    int offsets[tasks];
    int items[tasks];

    for (int i = 0; i < tasks; i++) {
        items[i] = rowsPerWorker * N;
        if (i < extra) items[i] += N;

        offsets[i] = offset;
        offset += items[i];
    }

    /* Scatter the rows appropriately */
    int myrows = items[rank] / N;

    /* Allocate an extra row of padding on either end */
    double *current = calloc((items[rank] + 2 * N), sizeof(double));
    double *old     = calloc((items[rank] + 2 * N), sizeof(double));

    if (DEBUG && rank == 0) fprintf(stderr, "scattering...\n");

    PMPI_Scatterv(initial, items, offsets, MPI_DOUBLE,
                  current + N, items[rank], MPI_DOUBLE, 0, MPI_COMM_WORLD);

    double t_scatter = MPI_Wtime();

    /*****************************************************************/
    /* CALCULATE                                                     */
    /*****************************************************************/
    MPI_Request req;
    double t_net = 0;

    for (int t = 0; t < T; t++) {
        if (DEBUG) fprintf(stderr, "Beginning iteration %d: rank %d\n", t, rank);

        /* Swap old and current so we can overwrite current */
        double *temp = current;
        current = old;
        old = temp;

        /* Hold onto some useful pointers into old */
        double *succrow  = old + N * (myrows + 1);
        double *predrow  = old;
        double *firstrow = old + N;
        double *lastrow  = old + myrows;
        double t_temp = MPI_Wtime();

        /* Send last row to succ and receive it from pred if eligible */
        if (succ < tasks) {
            PMPI_Isend(lastrow, N, MPI_DOUBLE,
                       succ, 0, MPI_COMM_WORLD, &req);
        }
        if (pred >= 0) {
            PMPI_Recv(predrow, N, MPI_DOUBLE, pred, 0, MPI_COMM_WORLD, 0);
        }

        /* Send first row to pred and receive it from succ if eligible */
        if (pred >= 0) {
            PMPI_Isend(firstrow, N, MPI_DOUBLE, pred, 0, MPI_COMM_WORLD, &req);
        }
        if (succ < tasks) {
            PMPI_Recv(succrow, N, MPI_DOUBLE, succ, 0, MPI_COMM_WORLD, 0);
        }

        t_net += MPI_Wtime() - t_temp;

        /* Determine current from old, predrow, and succrow */
        for (int j = 1; j <= myrows; j++) {
            for (int k = 0; k < N; k++) {

                /* Determine adjacent cells */
                double left = 0, right = 0;
                if (k > 0    ) left  = old[j * N + k - 1];
                if (k < N - 1) right = old[j * N + k + 1];

                double top    = old[(j - 1) * N + k];
                double bottom = old[(j + 1) * N + k];
                double focus  = old[j * N + k];

                /* Calculate the new cell value */
                current[j * N + k] = focus + .1 * (top + bottom - 2 * focus)
                                     + .1 * (left + right - 2 * focus);
            }

        }
    }

    free(old);
    double t_work = MPI_Wtime();

    /*****************************************************************/
    /* WRITE THE OUTPUT                                              */
    /*****************************************************************/
    PMPI_Gatherv(current + N, items[rank], MPI_DOUBLE, initial,
                 items, offsets, MPI_DOUBLE, 0, MPI_COMM_WORLD);

    double t_gather = MPI_Wtime();
    free(current);

    if (rank == 0 && !DEBUG) {
        FILE *out = fopen(argv[2], "w");

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                fprintf(out, "%d %d %lf\n", i, j, initial[i * N + j]);
            }
        }
        fclose(out);
    }

    double t2 = MPI_Wtime();

    if (rank == 0) {
        fprintf(stderr, "-----------------------------------------\n");
        fprintf(stderr, "TIMING INFORMATION                       \n");
        fprintf(stderr, "-----------------------------------------\n");
        fprintf(stderr, "RANK     INIT     READ  SCATTER     WORK   GATHER    WRITE    TOTAL     NET\n");
    }

    MPI_Barrier(MPI_COMM_WORLD);

    fprintf(stderr, "%4.2d %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f\n",
            rank, t_init - t1, t_read - t_init, t_scatter - t_read, t_work - t_scatter,
            t_gather - t_work, t2 - t_gather, t2 - t1, t_net);

    free(initial);

    MPI_Finalize();
    return 0;
}