/** 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 GlobalWalkerControl::swapWalkersBlocked(MCWalkerConfiguration& W) { NumSwaps++; OffSet[0]=0; for(int i=0; i<NumContexts; i++) OffSet[i+1]=OffSet[i]+NumPerNode[i]; FairPartition(Cur_pop,NumContexts,FairOffSet); int toLeft=FairOffSet[MyContext]-OffSet[MyContext]; int toRight=FairOffSet[MyContext+1]-OffSet[MyContext+1]; Walker_t& wRef(*W[0]); vector<Walker_t*> newW; int num_deleted=0; int last=NumPerNode[MyContext]-1; //scehdule irecv if(toLeft<0) { // recv from node-1 int dn=-toLeft; OOMPI_Packed recvBuffer(dn*wRef.byteSize(),OOMPI_COMM_WORLD); OOMPI_COMM_WORLD[MyContext-1].Recv(recvBuffer); while(dn) { Walker_t *awalker= new Walker_t(wRef); awalker->getMessage(recvBuffer); newW.push_back(awalker); --dn; } } else if(toLeft>0) { //send to node-1 int dn=toLeft; num_deleted+=dn; OOMPI_Packed sendBuffer(dn*wRef.byteSize(),OOMPI_COMM_WORLD); while(dn) { W[last]->putMessage(sendBuffer); --dn; --last; } OOMPI_COMM_WORLD[MyContext-1].Send(sendBuffer); } if(toRight<0) { // send to node+1 int dn=-toRight; num_deleted+=dn; OOMPI_Packed sendBuffer(dn*wRef.byteSize(),OOMPI_COMM_WORLD); while(dn) { W[last]->putMessage(sendBuffer); --dn; --last; } OOMPI_COMM_WORLD[MyContext+1].Send(sendBuffer); } else if(toRight>0) { //recv from node+1 OOMPI_Packed recvBuffer(toRight*wRef.byteSize(),OOMPI_COMM_WORLD); OOMPI_COMM_WORLD[MyContext+1].Recv(recvBuffer); int dn=toRight; while(dn) { Walker_t *awalker= new Walker_t(wRef); awalker->getMessage(recvBuffer); newW.push_back(awalker); --dn; } } while(num_deleted>0) { W.pop_back(); --num_deleted; } if(newW.size()) W.insert(W.end(),newW.begin(),newW.end()); }
/** swap Walkers with Irecv/Send * * The algorithm ensures that the load per node can differ only by one walker. * The communication is one-dimensional. */ void GlobalWalkerControl::swapWalkersAsync(MCWalkerConfiguration& W) { NumSwaps++; OffSet[0]=0; for(int i=0; i<NumContexts; i++) OffSet[i+1]=OffSet[i]+NumPerNode[i]; FairPartition(Cur_pop,NumContexts,FairOffSet); int toLeft=FairOffSet[MyContext]-OffSet[MyContext]; int toRight=FairOffSet[MyContext+1]-OffSet[MyContext+1]; Walker_t& wRef(*W[0]); int num_deleted=0; int last=NumPerNode[MyContext]-1; OOMPI_Packed* recvLeftBuffer=0; OOMPI_Packed* recvRightBuffer=0; OOMPI_Request recvLeftRequest; OOMPI_Request recvRightRequest; //initiate Irecv if(toLeft<0) { // recv from node-1 int dn=-toLeft; recvLeftBuffer = new OOMPI_Packed(dn*wRef.byteSize(),OOMPI_COMM_WORLD); recvLeftRequest = OOMPI_COMM_WORLD[MyContext-1].Irecv(*recvLeftBuffer,MPI_ANY_TAG); } if(toRight>0) { //recv from node+1 recvRightBuffer = new OOMPI_Packed(toRight*wRef.byteSize(),OOMPI_COMM_WORLD); recvRightRequest = OOMPI_COMM_WORLD[MyContext+1].Irecv(*recvRightBuffer,MPI_ANY_TAG); } //send the data if(toLeft>0) { //send to node-1 int dn=toLeft; num_deleted+=dn; OOMPI_Packed sendBuffer(dn*wRef.byteSize(),OOMPI_COMM_WORLD); while(dn) { W[last]->putMessage(sendBuffer); --dn; --last; } OOMPI_COMM_WORLD[MyContext-1].Send(sendBuffer); } if(toRight<0) { // send to node+1 int dn=-toRight; num_deleted+=dn; OOMPI_Packed sendBuffer(dn*wRef.byteSize(),OOMPI_COMM_WORLD); while(dn) { W[last]->putMessage(sendBuffer); --dn; --last; } OOMPI_COMM_WORLD[MyContext+1].Send(sendBuffer); } while(num_deleted>0) { W.pop_back(); --num_deleted; } if(recvLeftBuffer) { recvLeftRequest.Wait(); int dn=-toLeft; while(dn) { Walker_t *awalker= new Walker_t(wRef); awalker->getMessage(*recvLeftBuffer); W.push_back(awalker); --dn; } delete recvLeftBuffer; recvLeftBuffer=0; } if(recvRightBuffer) { recvRightRequest.Wait(); int dn=toRight; while(dn) { Walker_t *awalker= new Walker_t(wRef); awalker->getMessage(*recvRightBuffer); W.push_back(awalker); --dn; } delete recvRightBuffer; recvRightBuffer=0; } }