/** swap walkers using (low,high) ordered pairs * * The communication occur only between the (low,high) pairs. * This does not guarantee a perfect balance swapWalkersBlocked and swapWalkersAsync * try to achieve. However, the number of messages and their sizes are less than * other methods. */ void GlobalWalkerControl::swapWalkersMap(MCWalkerConfiguration& W) { NumSwaps++; multimap<int,int> nw_map; for(int i=0; i<NumContexts; i++) { nw_map.insert(pair<int,int>(NumPerNode[i],i)); } // multimap key is sorted with ascending order multimap<int,int>::iterator it(nw_map.begin()); multimap<int,int>::reverse_iterator it_b(nw_map.end()); bool notpaired=true; int target_context=-1; int half=NumContexts/2; int item=0; bool minorcontext; while(notpaired &&item<half) { int i=(*it).second; int j=(*it_b).second; if(i == MyContext) { target_context=j; notpaired=false; minorcontext=true; } else if(j == MyContext) { target_context= i; notpaired=false; minorcontext=false; } ++it; ++it_b; ++item; } int nw_tot=NumPerNode[MyContext]+NumPerNode[target_context]; int nw_L=nw_tot/2; int nw_R=nw_tot-nw_L; int dnw(0); if(minorcontext) { dnw=nw_L-NumPerNode[MyContext];//how many to get } else { dnw=NumPerNode[MyContext]-nw_R;//how many to send } if(dnw) {//something to swap if(minorcontext) {//open recv buffer Walker_t& wRef(*W[0]); OOMPI_Packed recvBuffer(dnw*wRef.byteSize(),OOMPI_COMM_WORLD); OOMPI_COMM_WORLD[target_context].Recv(recvBuffer); //create walkers int last = W.getActiveWalkers(); while(dnw) { Walker_t *awalker= new Walker_t(wRef); awalker->getMessage(recvBuffer); W.push_back(awalker); --dnw; ++last; } } else { Walker_t& wRef(*W[0]); OOMPI_Packed sendBuffer(dnw*wRef.byteSize(),OOMPI_COMM_WORLD); int last=W.getActiveWalkers()-1; while(dnw) { W[last]->putMessage(sendBuffer); --dnw; --last; } OOMPI_COMM_WORLD[target_context].Send(sendBuffer); //last=WalkerList.size()-1; //while(dnw_save) { // delete WalkerList[last]; // WalkerList.pop_back(); // --dnw_save; --last; //} //destroyWalkers(WalkerList.begin()+nsub[MyContext], WalkerList.end()); W.destroyWalkers(W.begin()+nw_R, W.end()); } } /* not used yet struct lessNode { inline bool operator()(const pair<int,int>& a, const pair<int,int>& b) const { return a.second < b.second; } }; //typedef pair<int,int> mytype; //vector<mytype> id2n(NumContexts); //for(int i=0; i<NumContexts; i++) { // id2n=pair<int,int>(i,NumPerNode[i]); //} // //std::sort(id2n.begin(),id2n.end(),lessNode); */ }
/** swap Walkers with Recv/Send * * The algorithm ensures that the load per node can differ only by one walker. * The communication is one-dimensional. */ void WalkerControlMPI::swapWalkersSimple(MCWalkerConfiguration& W) { NumSwaps++; FairDivideLow(Cur_pop,NumContexts,FairOffSet); vector<int> minus, plus; int deltaN; for(int ip=0; ip<NumContexts; ip++) { int dn=NumPerNode[ip]-(FairOffSet[ip+1]-FairOffSet[ip]); if(ip == MyContext) deltaN=dn; if(dn>0) { plus.insert(plus.end(),dn,ip); } else if(dn<0){ minus.insert(minus.end(),-dn,ip); } } Walker_t& wRef(*W[0]); vector<Walker_t*> newW; vector<Walker_t*> oldW; #ifdef MCWALKERSET_MPI_DEBUG char fname[128]; sprintf(fname,"test.%d",MyContext); ofstream fout(fname, ios::app); //fout << NumSwaps << " " << Cur_pop << " "; //for(int ic=0; ic<NumContexts; ic++) fout << NumPerNode[ic] << " "; //fout << " | "; //for(int ic=0; ic<NumContexts; ic++) fout << FairOffSet[ic+1]-FairOffSet[ic] << " "; //fout << " | "; for(int ic=0; ic<plus.size(); ic++) { fout << plus[ic] << " "; } fout << " | "; for(int ic=0; ic<minus.size(); ic++) { fout << minus[ic] << " "; } fout << endl; #endif int nswap=std::min(plus.size(), minus.size()); int last=W.getActiveWalkers()-1; int nsend=0; for(int ic=0; ic<nswap; ic++) { if(plus[ic]==MyContext) { //OOMPI_Packed sendBuffer(wRef.byteSize(),OOMPI_COMM_WORLD); OOMPI_Packed sendBuffer(wRef.byteSize(),myComm->getComm()); W[last]->putMessage(sendBuffer); //OOMPI_COMM_WORLD[minus[ic]].Send(sendBuffer); myComm->getComm()[minus[ic]].Send(sendBuffer); --last; ++nsend; } if(minus[ic]==MyContext) { //OOMPI_Packed recvBuffer(wRef.byteSize(),OOMPI_COMM_WORLD); OOMPI_Packed recvBuffer(wRef.byteSize(),myComm->getComm()); //OOMPI_COMM_WORLD[plus[ic]].Recv(recvBuffer); myComm->getComm()[plus[ic]].Recv(recvBuffer); Walker_t *awalker= new Walker_t(wRef); awalker->getMessage(recvBuffer); newW.push_back(awalker); } } if(nsend) { nsend=NumPerNode[MyContext]-nsend; W.destroyWalkers(W.begin()+nsend, W.end()); } //add walkers from other node if(newW.size()) W.insert(W.end(),newW.begin(),newW.end()); }