int MPI_Scatterv(void *sendbuf, int *sendcounts, int *displs, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm) { return PMPI_Scatterv(sendbuf, sendcounts, displs, sendtype, recvbuf, recvcount, recvtype, root, comm); }
int MPI_Scatterv(void *sbuff, int *scnts, int* displs, MPI_Datatype stype, void *rbuff, int rcnt, MPI_Datatype rtype, int root, MPI_Comm comm) { char call[COLLCHK_SM_STRLEN]; int g2g = 1, rank; int are2buffs; sprintf(call, "SCATTERV"); /* Check if init has been called */ g2g = CollChk_is_init(); if(g2g) { MPI_Comm_rank(comm, &rank); /* check for call consistency */ CollChk_same_call(comm, call); /* check for same root */ CollChk_same_root(comm, root, call); /* check for datatype signature consistency */ #if defined( HAVE_MPI_IN_PLACE ) /* are2buffs = ( rbuff != MPI_IN_PLACE || rank != root ); */ are2buffs = ( rank == root ? rbuff != MPI_IN_PLACE : 1 ); #else are2buffs = 1; #endif CollChk_dtype_scatterv(comm, stype, scnts, rtype, rcnt, root, are2buffs, call); /* make the call */ return PMPI_Scatterv(sbuff, scnts, displs, stype, rbuff, rcnt, rtype, root, comm); } else { /* init has not been called */ return CollChk_err_han("MPI_Init() has not been called!", COLLCHK_ERR_NOT_INIT, call, comm); } }
void ompi_scatterv_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Fint *displs, MPI_Fint *sendtype, char *recvbuf, MPI_Fint *recvcount, MPI_Fint *recvtype, MPI_Fint *root, MPI_Fint *comm, MPI_Fint *ierr) { MPI_Comm c_comm; MPI_Datatype c_sendtype, c_recvtype; int size, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(displs); c_comm = PMPI_Comm_f2c(*comm); c_sendtype = PMPI_Type_f2c(*sendtype); c_recvtype = PMPI_Type_f2c(*recvtype); PMPI_Comm_size(c_comm, &size); OMPI_ARRAY_FINT_2_INT(sendcounts, size); OMPI_ARRAY_FINT_2_INT(displs, size); sendbuf = (char *) OMPI_F2C_BOTTOM(sendbuf); recvbuf = (char *) OMPI_F2C_IN_PLACE(recvbuf); recvbuf = (char *) OMPI_F2C_BOTTOM(recvbuf); c_ierr = PMPI_Scatterv(sendbuf, OMPI_ARRAY_NAME_CONVERT(sendcounts), OMPI_ARRAY_NAME_CONVERT(displs), c_sendtype, recvbuf, OMPI_FINT_2_INT(*recvcount), c_recvtype, OMPI_FINT_2_INT(*root), c_comm); if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); OMPI_ARRAY_FINT_2_INT_CLEANUP(sendcounts); OMPI_ARRAY_FINT_2_INT_CLEANUP(displs); }
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; }