/* i would prefer that the thread initialization code happen in MPIMain(), but * it needs Population pop, which is declared here */ int MasterMaster(MasterGamlConfig& conf, HKYData& data) { Parameters params; params.SetParams(conf, data); LogParams(params); int nprocs; MPI_Comm_size(MPI_COMM_WORLD, &nprocs); bool poo=true; // while(poo); Tree::alpha = params.gammaShapeBrlen; Tree::meanBrlenMuts = params.meanBrlenMuts; Population pop; // debug_mpi("about to setup"); pop.Setup(params, &conf, nprocs, 0); g_sw=&pop.stopwatch; // debug_mpi("setup"); g_gen = &pop.gen; pop.CalcAverageFitness(); // start the thread pthread_t thread; thread_arg_t targ; pthread_mutex_init(&lock_pm, NULL); pthread_mutex_init(&lock_pop, NULL); pthread_cond_init(&cond_pm, NULL); g_quit_time = false; g_processing_message = false; targ.conf = &const_cast<MasterGamlConfig&>(conf); targ.pop = &pop; targ.nprocs = nprocs; pthread_create(&thread, NULL, thread_func2, (void*)&targ); cout << "Master running..." << endl; pop.gen=0; while (!g_quit_time){ pthread_mutex_lock(&lock_pop); pop.keepTrack(); pop.OutputFate(); if (pop.gen % conf.logevery == 0) pop.OutputLog(); ++pop.gen; pop.NextGeneration(); if(pop.gen % pop.params->saveEvery == 0) pop.CreateTreeFile( pop.params->treefname ); if(pop.gen % pop.adap->intervalLength == 0){ if(pop.enforceTermConditions == true && pop.gen-pop.lastTopoImprove > pop.lastTopoImproveThresh && pop.adap->improveOverStoredIntervals < pop.improveOverStoredIntervalsThresh && pop.adap->branchOptPrecision == pop.adap->minOptPrecision){ // && pop.paraMan->updateThresh == pop.paraMan->minUpdateThresh){ cout << "Reached termination condition!\nlast topological improvement at gen " << pop.lastTopoImprove << endl; cout << "Improvement over last " << pop.adap->intervalsToStore*pop.adap->intervalLength << " gen = " << pop.adap->improveOverStoredIntervals << endl; g_quit_time=true; break; } pop.CheckSubtrees(); //6-20-05 Changing this to deterministically reduce the replace thresh //every subtreeInterval generations. Tying the reduction of this to //how often the master recieved new bests from the remotes had odd properties, //and didn't scale well with differing numbers of processors. //and it's not clear what a better automated approach would be //pop.CheckRemoteReplaceThresh(); if(pop.gen % pop.paraMan->subtreeInterval == 0) pop.paraMan->ReduceUpdateThresh(); #ifdef INCLUDE_PERTURBATION pop.CheckPerturbParallel(); #endif } pthread_mutex_unlock(&lock_pop); pthread_mutex_lock(&lock_pm); while (g_processing_message) pthread_cond_wait(&cond_pm, &lock_pm); pthread_mutex_unlock(&lock_pm); } pop.FinalOptimization(); pthread_join(thread, NULL); return 0; }
int RemoteSubtreeWorker(Population& pop, const GeneralGamlConfig& conf){ int *which, size, rank, tag; char *tree_strings, *buf; double score, *models; bool perturb; which=new int[5]; MPI_Comm_rank(MPI_COMM_WORLD, &rank); pop.CalcAverageFitness(); int lastSend=g_sw->SplitTime(); cout << "Remote number " << rank << " running..." << endl; for (pop.gen = 1; pop.gen < conf.stopgen;){ pop.keepTrack(); pop.OutputFate(); if (pop.gen % conf.logevery == 0) pop.OutputLog(); ++pop.gen; pop.NextGeneration(); if(g_sw->SplitTime() - lastSend > conf.sendInterval){ debug_mpi("SYNCH COMM (node 0)"); //send our best individual to the master RemoteSendBestTree(pop); lastSend=g_sw->SplitTime(); if(pop.params->stoptime - g_sw->SplitTime() < 0){ debug_mpi("time limit of %d seconds reached...", pop.params->stoptime); break; } } //Check for a new tree from the master bool firstmessage=true; bool gotmessage=false; int subtreeNode; while(RecvMPIMessage(&tree_strings, &size, 0, &tag, false)==true){ //check for a quit message if(tag == TAG_QUIT) { debug_mpi("\trecv: quit message"); delete [] which; debug_mpi("quitting"); return 0; } // bool gotNewIndiv=false; int recievedDefNumber; debug_mpi("SYNCH COMM (node 0)"); gotmessage=true; assert(tag == TAG_TREE_STRINGS || tag==TAG_PERTURB); if(firstmessage==false) debug_mpi("\tfound a newer message..."); if(tag != TAG_PERTURB){ gotNewIndiv=true; RecvMPIMessage(&buf, &size, 0, &tag, true); assert(tag == TAG_MODEL); models=(double*) buf; debug_mpi("\tgot new ind" ); RecvMPIMessage(&buf, &size, 0, &tag, true); // if(tag != TAG_PERTURB){ perturb=false; assert(tag == TAG_SUBTREE_DEFINE); subtreeNode=atoi(buf); if(subtreeNode!=0){ delete []buf; RecvMPIMessage(&buf, &size, 0, &tag, true); assert(tag == TAG_SUBTREE_ITERATION); recievedDefNumber=atoi(buf); debug_mpi("\tworking on subtree def %d, node %d", recievedDefNumber, subtreeNode); } else recievedDefNumber=0; } else{ pop.pertMan->pertType=atoi(tree_strings); perturb=true; } //if the current best and the new tree are either both accurate for the same subtree def or both //inaccurate for subtrees, just replace the worst individual, rather than the // whole pop, that way if the tree is old and worse that what the remote // already has it won't matter if(gotNewIndiv){ *which=(int)pop.cumfit[0][0]; debug_mpi("\treplacing indiv %d", *which); pop.ReplaceSpecifiedIndividuals(1, which, tree_strings, models); if(recievedDefNumber!=pop.subtreeDefNumber || (pop.subtreeNode!=0 && subtreeNode!=0)){ pop.AssignSubtree(subtreeNode, *which); pop.CalcAverageFitness(); debug_mpi("\tfilling pop with clones of %d", *which); pop.SetNewBestIndiv(*which); pop.FillPopWithClonesOfBest(); pop.subtreeDefNumber=recievedDefNumber; } delete [] models; delete [] buf; } #ifdef INCLUDE_PERTURBATION if(perturb==true){ pop.CalcAverageFitness(); if(pop.pertMan->pertType==1){ debug_mpi("peforming NNI perturbation..."); int toReplace=(pop.bestIndiv == 0 ? 1 : 0); pop.AppendTreeToTreeLog(-1, pop.bestIndiv); pop.NNIPerturbation(pop.bestIndiv, toReplace); pop.SetNewBestIndiv(toReplace); pop.FillPopWithClonesOfBest(); pop.AppendTreeToTreeLog(-1, pop.bestIndiv); } else if(pop.pertMan->pertType==2){ debug_mpi("peforming SPR perturbation..."); int toReplace=(pop.bestIndiv == 0 ? 1 : 0); pop.AppendTreeToTreeLog(-1, pop.bestIndiv); pop.SPRPerturbation(pop.bestIndiv, toReplace); pop.SetNewBestIndiv(toReplace); pop.FillPopWithClonesOfBest(); pop.AppendTreeToTreeLog(-1, pop.bestIndiv); } else assert(0); } #endif delete [] tree_strings; tag=0; firstmessage=false; } if(gotmessage==true){ // if(pop.subtreeNode != subtreeNode) pop.AssignSubtree(subtreeNode); pop.CalcAverageFitness(); debug_mpi("\tbest score= %f", pop.indiv[*which].Fitness()); //DEBUG //pop.AppendTreeToTreeLog(rank, -1, *which); } } SendMPIMessage(NULL, 0, 0, TAG_QUIT); debug_mpi("\tsent: quit message"); delete [] which; debug_mpi("quitting"); return 0; }