/* * Simplified program in which pairs of neighboring processes periodically * exchange messages. Each process alternates exchanging messages with its * neighbors and "computing" (actually just waiting). * * This version uses synchronous sends/receives, so it more or less has to * use the method in exchange-alt.c of having even-numbered processes send first * and odd-numbered processes receive first. Requires that the number of * processes be even. * * Command-line arguments: number of exchange-then-compute cycles, time to * "compute" (wait), message length */ #include #include #include #include #include "utility.h" /* has error_exit() */ #include "cmdline.h" /* main program */ int main(int argc, char *argv[]) { int nprocs, myID, left_nbr, right_nbr; int *to_left, *to_right, *from_left, *from_right; int numsteps, compute_time, msglength; double start_time, end_time; double time_diff, max_time_diff; MPI_Status status; /* MPI initialization */ MPI_Init(&argc, &argv); MPI_Comm_size (MPI_COMM_WORLD, &nprocs); MPI_Comm_rank(MPI_COMM_WORLD, &myID); if (nprocs %2 != 0) { error_exit("number of processes must be even\n"); } /* process command-line arguments */ char *usage_msg = "usage is %s numsteps compute_time msglength\n"; numsteps = get_integer_arg_extended(argc, argv, 1, 1, "numsteps", usage_msg, (myID == 0), (void (*)(void))MPI_Finalize); compute_time = get_integer_arg_extended(argc, argv, 2, 1, "compute_time", usage_msg, (myID == 0), (void (*)(void))MPI_Finalize); msglength = get_integer_arg_extended(argc, argv, 3, 1, "msglength", usage_msg, (myID == 0), (void (*)(void))MPI_Finalize); if (myID == 0) { printf("synchronous send/receive\n"); printf("numsteps = %d, compute_time = %d, msglength = %d, nprocs = %d\n", numsteps, compute_time, msglength, nprocs); } /* initialization of other variables */ left_nbr = (myID == 0) ? nprocs-1 : myID - 1; right_nbr = (myID == (nprocs-1)) ? 0 : myID + 1; to_left = malloc(sizeof(*to_left) * msglength); to_right = malloc(sizeof(*to_right) * msglength); from_left = malloc(sizeof(*from_left) * msglength); from_right = malloc(sizeof(*from_right) * msglength); if (to_left == NULL || to_right == NULL || from_left == NULL || from_right == NULL) error_exit("unable to allocate space for buffers\n"); /* barrier before we start timing */ MPI_Barrier(MPI_COMM_WORLD); start_time = MPI_Wtime(); /* repeat numsteps times */ for (int k = 0; k < numsteps; ++k) { /* exchange information with neighbors */ if (myID % 2 == 0) { /* even-numbered processes send first */ MPI_Ssend(to_left, msglength, MPI_INT, left_nbr, 0, MPI_COMM_WORLD); MPI_Ssend(to_right, msglength, MPI_INT, right_nbr, 0, MPI_COMM_WORLD); MPI_Recv(from_left, msglength, MPI_INT, left_nbr, 0, MPI_COMM_WORLD, &status); MPI_Recv(from_right, msglength, MPI_INT, right_nbr, 0, MPI_COMM_WORLD, &status); } else { /* odd-numbered processes receive first */ MPI_Recv(from_right, msglength, MPI_INT, right_nbr, 0, MPI_COMM_WORLD, &status); MPI_Recv(from_left, msglength, MPI_INT, left_nbr, 0, MPI_COMM_WORLD, &status); MPI_Ssend(to_right, msglength, MPI_INT, right_nbr, 0, MPI_COMM_WORLD); MPI_Ssend(to_left, msglength, MPI_INT, left_nbr, 0, MPI_COMM_WORLD); } /* fake computation */ sleep(compute_time); } /* end timing */ end_time = MPI_Wtime(); time_diff = end_time - start_time; /* get maximum time over all processes */ MPI_Reduce(&time_diff, &max_time_diff, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD); /* print maximum time */ if (myID == 0) printf("time %g seconds\n", max_time_diff); /* clean up and end */ MPI_Finalize(); return EXIT_SUCCESS; }