#ifdef MPI #define SYNC_FIX_BY_RTJ 1 //#include //#include #include #include "SA_Synchronizer.h" //---- SA_Synchronizer --------------------------------------------------------- //#define nSYNC_DEBUG // define SYNC_DEBUG leads to warnings about late messages SA_Synchronizer::SA_Synchronizer(MPI_Comm comm): cluster(comm), MasterSlave(17), SlaveMaster(23), ClusterSync_ready(0), costs(NULL), arr_ind(NULL), arr_stat(NULL), founds(NULL), FoundTag(0), reqs(NULL) { SetCluster(comm); #ifdef SHOW_NFOUND NfoundSum = Nfoundi = 0; #endif } SA_Synchronizer::SA_Synchronizer(): MasterSlave(17), SlaveMaster(23), ClusterSync_ready(0), costs(NULL), arr_ind(NULL), arr_stat(NULL), founds(NULL), FoundTag(0), reqs(NULL) { #ifdef SHOW_NFOUND NfoundSum = Nfoundi = 0; #endif } void SA_Synchronizer::SetCluster(MPI_Comm comm) { FoundTag = 0; if (costs != NULL) {delete [] costs;costs = NULL;} if ( reqs != NULL) {delete [] reqs;reqs = NULL;} if(arr_ind != NULL) {delete [] arr_ind;arr_ind = NULL;} if ( arr_stat != NULL) {delete [] arr_stat;arr_stat = NULL;} if ( founds != NULL) {delete [] founds;founds = NULL;} int comp_res; MPI_Comm_compare(comm,MPI_COMM_SELF,&comp_res); if (comp_res == MPI_IDENT || comp_res == MPI_CONGRUENT) { cluster = comm; nproc = 1; me = 0; } else { MPI_Comm_dup(comm,&cluster); MPI_Comm_size(cluster, &nproc); MPI_Comm_rank(cluster,&me); if ( me == 0 ) { costs = new float[nproc]; founds = new int[nproc]; reqs = new MPI_Request[nproc]; arr_ind = new int[nproc]; arr_stat = new MPI_Status[nproc]; if (costs == NULL || founds == NULL || reqs == NULL || arr_ind == NULL || arr_stat == NULL) { std::cout <<"n"< costs[founds[best_i]]) best_i = i; } return founds[best_i]; } } // nur anhand der costs den gewaehlten Uebergang bestimmen int SA_Synchronizer::GetWinner(EXCHANGE_MODE exch_m) { int i=0,best_i=0; int nfound=0; //std::cout <<"n"<= INFINITY/2) best_i++; } else { for(best_i=nproc-1,i=nproc-2; i>=0;i--) if ( costs[i] < costs[best_i]) best_i = i; } #ifdef SHOW_NFOUND for(i=0;i=0;i--) { if ( costs[i] > costs[best_i]) best_i = i; } } #ifdef SHOW_NFOUND for(i=0;i -INFINITY/2 ) nfound++; } NfoundSum +=nfound; Nfoundi++; #endif } return best_i; } bool SA_Synchronizer::ClusterSyncNext(int found, float cost, EXCHANGE_MODE exch_m, int * root) /* Vorgehensweise beim nichttrivialem Cluster: MASTER: Benutzt IProbe, um found bei Slaves festzustellen und ISend, um allen anderen Slaves found mitzuteilen SLAVE: benutzt Send um found zu melden und cost mitzuteilen, und Iprobe, um found im Cluster zu erfahren Bei jedem Aufruf der Funktion: SLAVE: 1. Falls move_accepted: 1.1 Sende Message an Master: MPI_Send(cost) 1.2 MPI_Bcast(root,0) liefert Nummer des "Gluecklichen" 1.3 Pruefe mit MPI_Iprobe, ob kein Message vom Master vorliegt (moeglich!) 1.3.1 ggf. empfangen 1.4 return true; 2. sonst : MPI_Iprobe, ob ein Message vom Master ankommt: 2.1 ja => Empfange das Message vom Master MPI_Bcast(root,0) liefert Nummer des "Gluecklichen" return true; 3. return false; MASTER: 1. Falls move_accepted ODER ein MPI_IProbe ein Message vom SLAVE meldet: 1.1 Erzeuge eine Tabelle, wo fuer jeden SLAVE vermerkt wird, ob der bereits zum Bcast ging: 1.1.1 wiederhole fuer i von 1 bis nproc: 1.1.2 empfange alle vorliegende Nachrichten mit MPI_Recv, setze Eintraege in der Tabelle; 1.1.3 ist i gesetzt ? nein => sende Nachricht zu i (non-block: Issend); (*) [am Ende muss fuer jedes i gelten : entweder i found UND i.cost in der Tabelle oder i hat Isend empfangen, d.h. not found ] 1.2 Nummer des Gewinners bestimmen (exch_m und die Tabelle) 1.3 MPI_Bcast(root,0) verteilt Nummer des "Gluecklichen" 1.4 return true; 2. return false; */ { int flag=0; MPI_Status status; if ( me != 0) /*SLAVE*/ { if ( found) { FoundTag++; //MPE_Log_event(1,0,""); MPI_Ssend(&cost,1,MPI_FLOAT,0,FoundTag,cluster); //MPE_Log_event(2,0,""); //MPE_Log_event(9,0,""); MPI_Bcast(root,1,MPI_INT,0,cluster); //MPE_Log_event(10,0,""); //MPE_Log_event(3,0,""); MPI_Iprobe(0,MPI_ANY_TAG,cluster,&flag,&status); //MPE_Log_event(4,0,""); if (flag ) // Falls der Master einen Isend abgeschickt hat, d.h. bevor mein Send ankam { if (status.MPI_TAG != FoundTag ) // es ist aber ein Signal von dem NAECHSTEN Found !! { #ifdef SYNC_DEBUG std::cout<<"n"<= nproc, also = nproc, folglich sind alle Prozessoren bis zum Bcast durchgekommen. if (exch_m == MESSAGE) { *root = -1; } else { *root = GetWinner(exch_m,nfound); } //MPE_Log_event(9,0,""); MPI_Bcast(root,1,MPI_INT,0,cluster); //MPE_Log_event(10,0,""); InitReqsCosts(); // Arrays fuer das naechste Mal vorbereiten return ( 0 <= (*root)); } else return false; } } bool SA_Synchronizer::ClusterSyncOld(int found, float cost, EXCHANGE_MODE exch_m, int * root) /* Vorgehensweise beim nichttrivialem Cluster: MASTER: Benutzt IProbe, um found bei Slaves festzustellen und ISend, um allen anderen Slaves found mitzuteilen SLAVE: benutzt Send um found zu melden, und Iprobe, um found im Cluster zu erfahren Bei jedem Aufruf der Funktion: SLAVE: 1. Iprobe, ob Master einen Found meldet 1.1 ja => Recv, 1.2 Allreduce 1.3 return true; 2. Falls lokal found - 2.1 Send Found zum Master 2.2 Allreduce 2.3 Iprobe, ob Master Found meldet (moeglich) 2.3.1 ggf. Recv 2.4 return true; 3. return false; MASTER: 1. Falls move_accepted ODER ein MPI_IProbe ein Message vom SLAVE meldet: 1.1 fuer alle i von 1 bis nproc: sende Nachricht zu i (non-block: Issend); 1.2 Allreduce 1.3 Alle Founds mit gleichem FoundTag empfangen 1.4 return true; 2. return false; */ { int flag=0; MPI_Status status; if ( me != 0) /*SLAVE*/ { //MPE_Log_event(3,0,""); MPI_Iprobe(0,MPI_ANY_TAG,cluster,&flag,&status); //MPE_Log_event(4,0,""); if (flag ) // Falls der Master einen Isend abgeschickt hat { FoundTag++; if (status.MPI_TAG != FoundTag ) { std::cout<<"n"< Recv, 1.2 Gather,Bcast 1.3 return true; 2. Falls lokal found - 2.1 Send Found zum Master 2.2 Gather,Bcast 2.3 Iprobe, ob Master Found meldet (moeglich) 2.3.1 ggf. Recv 2.4 return true; 3. return false; MASTER: 1. Falls move_accepted ODER ein MPI_IProbe ein Message vom SLAVE meldet: 1.1 fuer alle i von 1 bis nproc: sende Nachricht zu i (non-block: Issend); 1.2 Gather,Bcast 1.3 Alle Founds mit gleichem FoundTag empfangen 1.4 return true; 2. return false; */ { int flag=0; MPI_Status status; cost = found ? cost : (OptType == Opt::MIN ? INFINITY : -INFINITY); if ( me != 0) /*SLAVE*/ { //MPE_Log_event(3,0,""); MPI_Iprobe(0,MPI_ANY_TAG,cluster,&flag,&status); //MPE_Log_event(4,0,""); if (flag ) // Falls der Master einen Isend abgeschickt hat { FoundTag++; if (status.MPI_TAG < FoundTag ) { #ifdef SYNC_DEBUG std::cout<<"n"< Recv, 1.2 Bcast 1.3 return true; 2. Falls lokal found - 2.1 Isend Found zum Master 2.2 Bcast 2.3 Iprobe, ob Master Found meldet (moeglich) 2.3.1 ggf. Recv 2.4 return true; 3. return false; MASTER: 1. Falls move_accepted ODER ein MPI_IProbe ein Message vom SLAVE meldet: 1.1 fuer alle i von 1 bis nproc: sende Nachricht zu i (non-block: Issend); 1.2 Bcast 1.3 Alle Founds mit gleichem FoundTag empfangen 1.4 return true; 2. return false; */ { int flag=0; MPI_Status status; cost = found ? cost : (OptType == Opt::MIN ? INFINITY : -INFINITY); if ( me != 0) /*SLAVE*/ { //MPE_Log_event(3,0,""); MPI_Iprobe(0,MPI_ANY_TAG,cluster,&flag,&status); //MPE_Log_event(4,0,""); if (flag ) // Falls der Master einen Isend abgeschickt hat { FoundTag++; if (status.MPI_TAG < FoundTag ) { #ifdef SYNC_DEBUG std::cout<<"n"<