////////////////////////////////////////////////////////////////////////// // Traveling Salesman Problem with MPI // Note: this is a C++ program. // // Process 0 manages the queue of incomplte paths, and keeps // track of the best path. // // All other processes are workers that get and put jobs from and into // the queue. Each time they get a path, they are also informed // about the best length so far. // // Note that, unlike previous examples, this one does not work with // only one process. // // Starting city is assumed to be city 0. ////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include "list.h" #include "tsp.h" int myrank, NumProcs, NumCities; int *Dist; /////////////////////////////////////////////////////////////////////////// Path::Path () { length=0; visited=1; for (int i=0; i0) { // Don't put path into queue; send it to one waiting process MPI_Send (&msg, MSGSIZE, MPI_INT, waiting[--nwait], REPLY_PATH_TAG, MPI_COMM_WORLD); } else { P = new Path(); P->Set (msg.length, msg.city, msg.visited); queue.Insert(P, msg.length); } break; case GET_PATH_TAG: if (!queue.IsEmpty()) { // get a path and send it along with bestlength P = (Path *)queue.Remove(NULL); msg.length = P->length; memcpy (msg.city, P->city, MAXCITIES*sizeof(int)); msg.visited = P->visited; MPI_Send (&msg, MSGSIZE, MPI_INT, status.MPI_SOURCE, REPLY_PATH_TAG, MPI_COMM_WORLD); delete P; } else { // requester must wait waiting[nwait++] = status.MPI_SOURCE; if (nwait==NumProcs-1) // Tell everbody that we're done for (int i=1; i msg.visited-1) { int tmp = msg.city[msg.visited-1]; msg.city[msg.visited-1] = msg.city[i]; msg.city[i] = tmp; } // visit city[visited-1] if (int d = Dist[(msg.city[msg.visited-2])*NumCities + msg.city[msg.visited-1] ]) { msg.length = length + d; if (msg.length < shortestLength) MPI_Send (&msg, MSGSIZE, MPI_INT, 0, PUT_PATH_TAG, MPI_COMM_WORLD); } } } MPI_Send (NULL, 0, MPI_INT, 0, GET_PATH_TAG, MPI_COMM_WORLD); } } int main(int argc, char *argv[]) { MPI_Init (&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &myrank); MPI_Comm_size(MPI_COMM_WORLD, &NumProcs); if (NumProcs<2) { printf("At least 2 processes are required\n"); exit(-1); } // Initialize distance matrix. Ususally done by one process // and bcast, or initialized from a file in a shared file system. Fill_Dist(); // process 0 read the data and broadcast it to the others if (myrank==0) Coordinator(); else Worker(); MPI_Finalize(); return 0; }