#ifdef MPI //#include //#include #include #include //#include #include #include //#include #include #include #include //#include #include //#include #include "SA_ParSolver.h" #include "SA_ParScheduler.h" #include "util_salib.h" #include "AllSchedulers.h" int myrank=-1; // Prozessornummer - globale Variable const int MaxStringLength = 1024; // bound for the stringlength in the logfile // \****************************************************** // Konstruktor - Liest die Konfigurationsdatei mit Hilfe // der Methode ReadConfigFile. // \****************************************************** SA_ParSolver::SA_ParSolver(SA_Problem & prb) : SA_Solver::SA_Solver(prb) { } // \****************************************************** // Destruktor // \****************************************************** SA_ParSolver::~SA_ParSolver() { delete Cooler; } void SA_ParSolver::SetScheduler(SA_ParScheduler *nscheduler) { Cooler = nscheduler; SA_Solver::Cooler = nscheduler; } // \****************************************************** // Methode OutputStatistics - Statistiken des Laufs in ein stream schreiben (Mit std::endl!) // in comm stehen Rechnerknoten, fuer die zusammen EINE Zeile hingeschrieben wird // \****************************************************** void SA_ParSolver::OutputStatistics(std::ostream & output, MPI_Comm comm) {//debug(SA_ParSolver::OutputStatistics , myrank); // Besten Kostenwert nach dem Postprocessing ermitteln float BestBuff, BestPostE = P->GetCost(*BestSolution); // Ausgabe der Daten: F=Dateiname,T=Anfangstemperatur, C=Abkuehlungsfaktor, Z=Lese-/Rechenzeit int me,nproc; int flag; MPI_Initialized(&flag); if (flag) { if ( OptType == Opt::MIN ) MPI_Reduce(&BestPostE,&BestBuff,1,MPI_FLOAT,MPI_MIN,0,comm); else MPI_Reduce(&BestPostE,&BestBuff,1,MPI_FLOAT,MPI_MAX,0,comm); MPI_Comm_rank(comm,&me); MPI_Comm_size(comm,&nproc); if (me == 0) { output << "Solv=Seq" << " NPROC=1" << " F=" << filename(DataFileName) << " Z=" << FileReadTime << "/" << InitialSolutionTime << "/" << SATime << "/" << PostprocTime << " StartSol=" << ( GetInitialSolution_fp == & SA_Problem::GetRandomSolution ? "Rnd":"Init") <<" "; Cooler->CreateLog(output,comm); output << " PostE=" << BestBuff <CreateLog(std::cout,comm); } } else { SA_Solver::CreateLog(output); Cooler->CreateLog(output,comm); } } // Shows the configuration of the used scheduler void SA_ParSolver::ShowConfig() { SA_Solver::ShowConfig(); Cooler->ShowConfig(std::cout); } // Startloesungen erzeugen und ggf. ausgeben void SA_ParSolver::InitStates() {//debug(SA_ParSolver::InitStates, myrank); time_t starttime, endtime; int things_done=0; // Initialloesung erzeugen if( State == NULL) { State = P->CreateSolution(); things_done = 1; } if (BestSolution == NULL ) BestSolution = P->CreateSolution(); InitialSolutionTime = time(NULL); (*P.*GetInitialSolution_fp)(*State); InitialSolutionTime = time(NULL)- InitialSolutionTime; Cooler->SetStartE(P->GetCost(*State)); Cooler->ResetBestE(); P->Copy(*State,*BestSolution); if( things_done && myrank <= 0) { if ( VerboseMode ) { std::cout << "Initial solution"<< (myrank ==0 ? " auf proc 0":"")<< "\n"; std::cout << *State <GetCost(*State)<GetLocalN(); if( Length <= 0 ) { std::cout << "Bad value "<GetNeighbor(*State,1); std::cout<<"\tSingle GetNeighbor : done\n"; P->UpdateSolution(*State); std::cout<<"\tUpdateSolution : done\n"; do { Cost = P->GetCost(*State); P->Copy(*State,*BestSolution); P->GetNeighbor(*State,1); P->ResetSolution(*State); if ( (Cost - P->GetCost(*State)) > EPSILON ) { status = 0; std::cout<< "Error: the solution \n"<< (*BestSolution) <<" went after GetNeigbor and ResetSoltuion into\n" << (*State) <<" and the costvalue has changed!\n"; } P->GetNeighbor(*State,1); Cost = P->GetCost(*State); P->UpdateSolution(*State); if ( (Cost - P->GetCost(*State)) > EPSILON ) { status = 0; std::cout<< "Error: the solution \n"<< (*State)<<"changed the costvalue after UpdateSolution!\n"; } } while (status && (i++)StartClock(); Cooler->WarmingUp(*P,*State,*BestSolution,MPI_COMM_SELF); ShowConfig(); time_t starttime, endtime; P->GetInitialSolution(*State); starttime = time(NULL); do { do { P->GetNeighbor(*State,Cooler->GetRelativeT()); if ( Cooler->Accept( P->GetCost(*State) )) { P->UpdateSolution(*State); if ( Cooler->BestFound() ) P->Copy(*State,*BestSolution); } else P->ResetSolution(*State); } while ( ! Cooler->Equilibrium()); if ( VerboseMode ) { Cooler->OutputSubchainStatistics(std::cout); std::cout <UpdateTemperature(); //MPE_Log_event(4,0,"End UpdateTemperature"); } while (! Cooler->Frozen()); if (Cooler->TimeExceeded()) { std::cout << "TIME LIMIT EXPIRED!!! \n Annealing process stoppt! \n"; } endtime = time(NULL); SATime = endtime - starttime; PostprocTime = time(NULL); P->Postprocessing(*BestSolution); PostprocTime = time(NULL) - PostprocTime; WriteLog(1,MPI_COMM_WORLD,MPI_COMM_SELF); WriteSolutionParallel(MPI_COMM_WORLD); return Cooler->GetBestE(); } //void SA_ParSolver::CreateLog(std::ostream &output, MPI_Comm comm) { // // Besten Kostenwert nach dem Postprocessing ermitteln // float BestBuff, // BestPostE = P->GetCost(*BestSolution); // //// Ausgabe der Daten: F=Dateiname,T=Anfangstemperatur, C=Abkuehlungsfaktor, Z=Lese-/Rechenzeit // int me,nproc; // int flag; // MPI_Initialized(&flag); // if (flag) // { // if ( OptType == Opt::MIN ) // MPI_Reduce(&BestPostE,&BestBuff,1,MPI_FLOAT,MPI_MIN,0,comm); // else // MPI_Reduce(&BestPostE,&BestBuff,1,MPI_FLOAT,MPI_MAX,0,comm); // // MPI_Comm_rank(comm,&me); // MPI_Comm_size(comm,&nproc); // // if (me == 0) // { // output // << "Solv=Seq" // << " NPROC=1" // << " F=" << filename(DataFileName) // << " Z=" << FileReadTime << "/" << InitialSolutionTime << "/" << SATime << "/" << PostprocTime // << " StartSol=" << ( GetInitialSolution_fp == & SA_Problem::GetRandomSolution ? "Rnd":"Init") // <<" "; // // Cooler->CreateLog(output,comm); // output << " PostE=" << BestBuff <CreateLog(std::cout,comm); // } // } // else // { // SA_Solver::CreateLog(output); // } //} // Statistik(en) der Laeufe nacheinander in die Logdatei schreiben. // Die Funktion wird auf allen Prozessoren von MPI_COMM_WORLD aufgerufen; // write==true <=> der Prozessor schreibt EIGENE Zeile in die Logdatei, // in comm_masters von solchen Prozessoren steht der genau sie enthaltender Communicator. // comm_slaves enthaelt jeweils alle Slaves zu einem Master. // // Bspl. : // WriteLog(1,MPI_COMM_WORLD,MPI_COMM_SELF); (== WriteLog(1);) // bedeutet : jeder Prozessor fuehrte eigenen Lauf durch, entsprechend muessen alle eine Zeile schreiben, // wo nur von mir stammende Information zusammengefasst wird. // WriteLog(myrank==0,MPI_COMM_SELF,MPI_COMM_WORLD); // besagt dagegen : alle zusammen machten einen Lauf, es wird eine Zeile geschrieben, und darin // steht Zusammenfassung von allen. void SA_ParSolver::WriteLog(bool write,MPI_Comm comm_masters, MPI_Comm comm_slaves) { if( write ) { char * log_buf = new char [MaxStringLength], * str=NULL; if (log_buf == NULL) { std::cout <<"at n"<= 0) // Falls in MPI-Umgebung { int np,mr; MPI_Comm_size(comm,&np); MPI_Comm_rank(comm,&mr); struct { float cost_value; int rank; } my_config, best_config; my_config.cost_value = P->GetCost(*BestSolution); my_config.rank = mr; if ( OptType == Opt::MIN ) MPI_Allreduce(&my_config,&best_config,1,MPI_FLOAT_INT,MPI_MINLOC,comm); else MPI_Allreduce(&my_config,&best_config,1,MPI_FLOAT_INT,MPI_MAXLOC,comm); //std::cout <GetBestE()<<" BestSolution "<GetCost(*BestSolution); my_config.rank = myrank; MPI_Barrier(MPI_COMM_WORLD); if ( OptType == Opt::MIN ) MPI_Allreduce(&my_config,&best_config,1,MPI_FLOAT_INT,MPI_MINLOC,comm); else MPI_Allreduce(&my_config,&best_config,1,MPI_FLOAT_INT,MPI_MAXLOC,comm); std::cout << myrank << ": my BestE " << Cooler->GetBestE() << " my BestSolution " << my_config.cost_value << " real BestE " << best_config.cost_value << " on process " << best_config.rank << std::endl; P->BcastSolution(*BestSolution, best_config.rank, comm, myrank); std::cout << myrank << ": my BestE " << Cooler->GetBestE() << " my BestSolution " << P->GetCost(*BestSolution) << " real BestE " << best_config.cost_value << " on process " << best_config.rank << std::endl; } } #endif