/* * Generic example of master/worker program. "Tasks" just consist of sleeping * for a specified time; times to wait are generatedly randomly from 0 to a * specified maximum. * * Command-line arguments: total tasks, maximum task time, * (optional) "--verbose" for verbose output * * Parallel version using MPI and static assignment of tasks to workers. */ #include #include #include #include /* a short function to print a message and exit */ void error_exit(char msg[]) { fprintf(stderr, "%s", msg); MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); } /* function to generate a random integer in [start, end] */ int random_in_range(int start, int end) { /* use method described in "rand" man page */ return start + ((double) (end-start+1) * rand()/(RAND_MAX + 1.0)); } /* ---- main program ---- */ int main(int argc, char *argv[]) { int num_tasks; int max_task_time; double start_time, end_time; int i; int task_time; int total_task_time = 0; int max_process_total_task_time; int min_process_total_task_time; int process_total_task_time = 0; int process_num_tasks = 0; int verbose = 0; int nprocs; int process_ID; if (MPI_Init(&argc, &argv) != MPI_SUCCESS) { fprintf(stderr, "MPI initialization error\n"); exit(EXIT_FAILURE); } if (argc < 3) { error_exit("usage: master-worker num_tasks max_task_time (millisecs) [--verbose]\n"); } num_tasks = atoi(argv[1]); max_task_time = atoi(argv[2]); if (argc > 3) verbose = 1; MPI_Comm_size(MPI_COMM_WORLD, &nprocs); MPI_Comm_rank(MPI_COMM_WORLD, &process_ID); MPI_Barrier(MPI_COMM_WORLD); start_time = MPI_Wtime(); for (i = 0; i < num_tasks; ++i) { /* generate full sequence of random numbers, but discard most */ task_time = random_in_range(1, max_task_time); if ((i % nprocs) == process_ID) { process_total_task_time += task_time; ++process_num_tasks; if (verbose) printf("(process %d) task time = %d\n", process_ID, task_time); usleep(task_time * 1000); } } printf("process %d number of tasks = %d, total time = %d\n", process_ID, process_num_tasks, process_total_task_time); MPI_Reduce(&process_total_task_time, &max_process_total_task_time, 1, MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD); MPI_Reduce(&process_total_task_time, &min_process_total_task_time, 1, MPI_INT, MPI_MIN, 0, MPI_COMM_WORLD); MPI_Reduce(&process_total_task_time, &total_task_time, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD); end_time = MPI_Wtime(); if (process_ID == 0) { printf("\nMPI parallel version with %d processes\n", nprocs); printf("number of tasks = %d\n", num_tasks); printf("max task time = %d\n", max_task_time); printf("total task time = %d\n", total_task_time); printf("total task time in processes ranges from %d to %d\n", min_process_total_task_time, max_process_total_task_time); printf("running time = %g\n", end_time - start_time); } MPI_Finalize(); return EXIT_SUCCESS; }