コード例 #1
0
/** 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);
  */
}
コード例 #2
0
/** 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());
}