/* * 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 asynchronous sends/receives and overlaps computation and * communication. * * 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_Request req_recv_L, req_recv_R, req_send_L, req_send_R; /* MPI initialization */ MPI_Init(&argc, &argv); MPI_Comm_size (MPI_COMM_WORLD, &nprocs); MPI_Comm_rank(MPI_COMM_WORLD, &myID); /* 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("nonblocking 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) { /* initiate communication to exchange information */ MPI_Irecv(from_left, msglength, MPI_INT, left_nbr, 0, MPI_COMM_WORLD, &req_recv_L); MPI_Irecv(from_right, msglength, MPI_INT, right_nbr, 0, MPI_COMM_WORLD, &req_recv_R); MPI_Isend(to_left, msglength, MPI_INT, left_nbr, 0, MPI_COMM_WORLD, &req_send_L); MPI_Isend(to_right, msglength, MPI_INT, right_nbr, 0, MPI_COMM_WORLD, &req_send_R); /* fake computation (what I can do now) */ sleep(compute_time); /* wait for communication to complete */ MPI_Wait(&req_recv_L, &status); MPI_Wait(&req_recv_R, &status); MPI_Wait(&req_send_L, &status); MPI_Wait(&req_send_R, &status); /* finish computation */ } /* 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; }