#ifdef MPI #include "SA_ClusteringScheduler.h" //---- SA_ClusteringScheduler --------------------------------------------------------- #include "math.h" SA_ClusteringScheduler::SA_ClusteringScheduler() : SA_ParScheduler(), act_cluster(0), do_clustering(0), n_cluster(1), cluster_size(1), mean_update_ratio(-1), // zeigt, da"s keine Mittelwerte "uber mehrere Prozessoren gebildet wurden mean_accept_ratio(-1), // dto. saclustoutput("SA_ClusteringScheduler","SA_Output.rsc") { saclustoutput.EnableLevelNumbers(false); saclustoutput.EnableIdentifier(true); saclustoutput.SetOutputLevel(10); saclustoutput.AddVariable(1,SA_LONG,&act_cluster); saclustoutput.AddVariable(2,SA_LONG,&do_clustering); saclustoutput.AddVariable(3,SA_LONG,&n_cluster); saclustoutput.AddVariable(4,SA_LONG,&cluster_size); saclustoutput.AddVariable(5,SA_DOUBLE, &mean_update_ratio); saclustoutput.AddVariable(6,SA_DOUBLE,&mean_accept_ratio); saclustoutput.SetPreviousOutput(SA_ParScheduler::GetSchedulerOutput()); } SA_Output * SA_ClusteringScheduler::GetSchedulerOutput() { return(&saclustoutput); } // Sum, Sum2, n_iter werden von allen Mitgliedern von comm // auf dem Prozess mit der Nummer 0 in comm gesammelt ( kann in UpdateTemperature verwendet werden) // setzt auch // mean_update_ratio // mean_accept_ratio // auf proc 0. // WICHTIG : Diese Funktion darf hoechstens einmal pro Temperaturstufe aufgerufen werden!! void SA_ClusteringScheduler::CollectSubchainStatistics(MPI_Comm comm) {//debug(SA_ClusteringScheduler::CollectSubchainStatistics , myrank); //MPE_Log_event(101,0,"Start CollectSubchainStatistics"); int me,nproc; MPI_Comm_size(comm,&nproc); if (nproc == 1) { mean_accept_ratio = GetAcceptRatio(); mean_update_ratio = GetUpdateRatio(); return; // Trivialfall - comm besteht nur aus einem Prozessor - mich } MPI_Comm_rank(comm,&me); struct { double S,S2,n,acc_r,upd_r; } in, out; in.S = Sum; in.S2 = Sum2; in.n = (double)n_iter; in.acc_r = GetAcceptRatio(); in.upd_r = GetUpdateRatio(); MPI_Reduce(&in,&out,5,MPI_DOUBLE,MPI_SUM,0,comm); if( me == 0 ) { Sum = out.S; Sum2 = out.S2; n_iter = (unsigned long) out.n; mean_accept_ratio = out.acc_r/nproc; mean_update_ratio = out.upd_r/nproc; } //MPE_Log_event(102,0,"End CollectSubchainStatistics"); } // Chief verteilt die Auftraege ; TRUE <=> SA noch nicht abgeschlossen ( also not frozen ) // insbes.: neue Temperatur setzen ! int SA_ClusteringScheduler::BroadcastSubchainOrder(MPI_Comm comm) {//debug(SA_ClusteringScheduler::BroadcastSubchainOrder, myrank); int me,nproc; MPI_Comm_size(comm,&nproc); if (nproc == 1) { UpdateTemperature(); return Frozen(); } MPI_Comm_rank(comm,&me); struct { float t; unsigned long f,a,d; } order; if ( me == 0 ) // ich bin der Chief { UpdateTemperature(); order.t = T; order.f = Frozen(); order.a = GetActCluster(); order.d = GetDoClustering(); MPI_Bcast(&order, sizeof(order) , MPI_BYTE, 0, comm); } else { MPI_Bcast(&order, sizeof(order) , MPI_BYTE, 0, comm); SetNewT(order.t); SetActCluster((unsigned long)order.a); SetDoClustering((unsigned long)order.d); } return (int)order.f; } // Die mittleren Raten bei aktueller Temperatur : falls nicht gesetzt (-1), werden Standardwerte von Scheduler geliefert double SA_ClusteringScheduler::GetMeanUpdateRatio() { return (mean_update_ratio >= 0) ? mean_update_ratio : GetUpdateRatio(); } double SA_ClusteringScheduler::GetMeanAcceptRatio() { return (mean_accept_ratio>=0) ? mean_accept_ratio : GetAcceptRatio(); } // \****************************************************** // Methode OutputSubchainStatistics - Schreibt die Daten der Teilkette(n) // // Sinnvoll : auf dem CHIEF-Knoten nach CollectSubchainStatistics // \****************************************************** void SA_ClusteringScheduler::OutputSubchainStatistics(std::ostream & output) {//debug(SA_ClusteringScheduler::OutputSubchainStatistics , myrank); //// Beste gesehene Loesungsbewertung: // float BestBuff; // if ( OptType == Opt::MIN ) // MPI_Reduce(&BestE,&BestBuff,1,MPI_FLOAT,MPI_MIN,0,comm); // else // MPI_Reduce(&BestE,&BestBuff,1,MPI_FLOAT,MPI_MAX,0,comm); // output // << " \nNdT=" << n_dT // << " T=" << T // << " Iter(T)=" << n_iter // << " RealIter(T)=" < 1) // { // int adjust = (int)ceil(cluster_size/2.0); // n_iter -= adjust; // Sum -= E*adjust; // Sum2 -= E*E*adjust; // } // Scheduler::SetNewE(e); //} // set the number and size of the cluster void SA_ClusteringScheduler::SetClusterNumber(unsigned long n_clu, unsigned long clu_size) { n_cluster= n_clu; cluster_size = clu_size; } #endif