source: XIOS/dev/dev_trunk_omp/src/event_scheduler.cpp @ 1745

Last change on this file since 1745 was 1745, checked in by yushan, 5 years ago

Generic_testcase: build flag --omp to enable EP with intelmpi. --omp2 to enable EP with openmpi. tested on Irene with compiler=intel17, mpi=intelmpi&openmpi, with and without EP

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
  • Property svn:eol-style set to native
File size: 7.2 KB
Line 
1#include "event_scheduler.hpp"
2#include "xios_spl.hpp"
3#include "mpi.hpp"
4#include "tracer.hpp"
5
6#ifdef _usingEP
7using namespace ep_lib;
8#endif
9
10namespace xios
11{
12 
13 
14  CEventScheduler::CEventScheduler(const MPI_Comm& comm) 
15  {
16    MPI_Comm_dup(comm, &communicator) ;
17    MPI_Comm_size(communicator,&mpiSize) ;
18    MPI_Comm_rank(communicator,&mpiRank);
19
20
21    int maxChild=1 ;
22
23    int m ;
24    do
25    {
26      m=1 ;
27      maxChild=maxChild+1 ;
28      for(int i=0;i<maxChild;i++) m=m*maxChild ;
29     } while(m<mpiSize) ;
30   
31   
32    int maxLevel=0 ;
33    for(int size=1; size<=mpiSize; size*=maxChild) maxLevel++ ; 
34
35    int begin, end, nb ;
36    int pos, n ;
37 
38    parent=vector<int>(maxLevel+1) ;
39    child=vector<vector<int> >(maxLevel+1,vector<int>(maxChild)) ;
40    nbChild=vector<int> (maxLevel+1) ;
41   
42    level=0 ;
43    begin=0 ;
44    end=mpiSize-1 ;     
45    nb=end-begin+1 ;
46     
47    do
48    {
49      n=0 ;
50      pos=begin ;
51      nbChild[level]=0 ;
52      parent[level+1]=begin ;
53      for(int i=0;i<maxChild && i<nb ;i++)
54      {
55        if (i<nb%maxChild) n = nb/maxChild + 1 ;
56        else n = nb/maxChild ;
57     
58        if (mpiRank>=pos && mpiRank<pos+n)
59        {
60          begin=pos ;
61          end=pos+n-1 ;
62        }
63        child[level][i]=pos ;
64        pos=pos+n ;
65        nbChild[level]++ ;
66      } 
67      nb=end-begin+1 ;
68      level=level+1 ;
69    } while (nb>1) ;
70
71   
72  }
73
74  CEventScheduler::~CEventScheduler()
75  {
76
77  } 
78
79  void CEventScheduler::registerEvent(const size_t timeLine, const size_t contextHashId)
80  {
81    registerEvent(timeLine, contextHashId, level) ;
82  }
83 
84  void CEventScheduler::registerEvent(const size_t timeLine, const size_t contextHashId, const size_t lev)
85  {
86       
87    traceOff() ;
88    SPendingRequest* sentRequest=new SPendingRequest ;
89    sentRequest->buffer[0]=timeLine ;
90    sentRequest->buffer[1]=contextHashId ;
91    sentRequest->buffer[2]=lev-1 ;
92
93    pendingSentParentRequest.push(sentRequest) ;
94    MPI_Isend(sentRequest->buffer,3, MPI_UNSIGNED_LONG, parent[lev], 0, communicator, &sentRequest->request) ;
95    traceOn() ;
96  } 
97
98  bool CEventScheduler::queryEvent(const size_t timeLine, const size_t contextHashId)
99  {
100
101    if (! eventStack.empty() && eventStack.front().first==timeLine && eventStack.front().second==contextHashId)
102    {
103      eventStack.pop() ;
104      return true ;
105    }
106    else return false ; 
107  } 
108 
109  void CEventScheduler::checkEvent(void)
110  {
111    traceOff() ;
112    checkChildRequest() ;
113    checkParentRequest() ;
114    traceOn() ;
115   
116  }
117 
118  void CEventScheduler::checkParentRequest(void)
119  {
120    int completed ;
121    MPI_Status status ;
122    int received ;
123    SPendingRequest* recvRequest ;
124    completed=true ;
125   
126    // check sent request to parent
127    while (! pendingSentParentRequest.empty() && completed)
128    {
129      MPI_Test( & pendingSentParentRequest.front()->request, &completed, &status) ;
130      if (completed) 
131      {
132        delete pendingSentParentRequest.front() ;
133        pendingSentParentRequest.pop() ;
134      }
135    }
136   
137    // probe if a message is coming from parent
138    received=true ;
139    while(received)
140    {
141      #ifdef _usingEP
142      MPI_Iprobe(-2,1,communicator,&received, &status) ;
143      #else     
144      MPI_Iprobe(MPI_ANY_SOURCE,1,communicator,&received, &status) ;
145      #endif
146      if (received)
147      {
148        recvRequest=new SPendingRequest ;
149        #ifdef _usingEP
150        MPI_Irecv(recvRequest->buffer, 3, MPI_UNSIGNED_LONG, -2, 1, communicator, &(recvRequest->request)) ;
151        #else
152        MPI_Irecv(recvRequest->buffer, 3, MPI_UNSIGNED_LONG, MPI_ANY_SOURCE, 1, communicator, &(recvRequest->request)) ;
153        #endif
154        pendingRecvParentRequest.push(recvRequest) ;
155      }
156    }
157   
158     // check sent request from parent
159    completed=true ;
160    while (! pendingRecvParentRequest.empty() && completed)
161    {
162      recvRequest=pendingRecvParentRequest.front() ;
163      MPI_Test( &(recvRequest->request), &completed, &status) ;
164      if (completed) 
165      {
166        size_t timeLine=recvRequest->buffer[0] ;
167        size_t hashId=recvRequest->buffer[1] ;
168        size_t lev=recvRequest->buffer[2] ;
169        delete recvRequest ;
170        pendingRecvParentRequest.pop() ;       
171 
172        if (lev==level) eventStack.push(pair<size_t,size_t>(timeLine,hashId)) ;
173        else  bcastEvent(timeLine, hashId, lev) ;
174      }
175    }   
176   
177  }
178
179  void CEventScheduler::checkChildRequest(void)
180  {
181// function call only by parent mpi process
182
183    MPI_Status status ; 
184    int received ;
185    received=true ;
186    SPendingRequest* recvRequest ;
187   
188    // check for posted requests and make the corresponding receive
189    while(received)
190    {
191      #ifdef _usingEP
192      MPI_Iprobe(-2,0,communicator,&received, &status) ;
193      #else
194      MPI_Iprobe(MPI_ANY_SOURCE,0,communicator,&received, &status) ;
195      #endif
196      if (received)
197      {
198        recvRequest=new SPendingRequest ;
199        #ifdef _usingEP
200        MPI_Irecv(recvRequest->buffer, 3, MPI_UNSIGNED_LONG, -2, 0, communicator, &recvRequest->request) ;
201        #else
202        MPI_Irecv(recvRequest->buffer, 3, MPI_UNSIGNED_LONG, MPI_ANY_SOURCE, 0, communicator, &recvRequest->request) ;
203        #endif
204        pendingRecvChildRequest.push_back(recvRequest) ;
205      }
206    }
207   
208    // check if receive request is achieved
209   
210    for(list<SPendingRequest*>::iterator it=pendingRecvChildRequest.begin(); it!=pendingRecvChildRequest.end() ; )
211    {
212      MPI_Test(&((*it)->request),&received,&status) ;
213      if (received)
214      {
215        size_t timeLine=(*it)->buffer[0] ;
216        size_t hashId=(*it)->buffer[1] ;
217        size_t lev=(*it)->buffer[2] ;
218       
219        SEvent event={timeLine,hashId,lev} ;
220        delete *it ; // free mem
221        it=pendingRecvChildRequest.erase(it) ; // get out of the list
222       
223        map< SEvent,int>::iterator itEvent=recvEvent.find(event) ;
224        if (itEvent==recvEvent.end()) 
225        {
226          itEvent=(recvEvent.insert(pair< SEvent ,int > (event,1))).first ;
227 
228        }
229        else (itEvent->second)++ ;
230        if (itEvent->second==nbChild[lev])
231        {
232          if (lev==0)
233          {
234            bcastEvent(timeLine,hashId,lev) ;
235            recvEvent.erase(itEvent) ;
236          }
237          else
238          {
239            registerEvent( timeLine,hashId,lev) ;
240          }
241        }
242      }
243      else ++it ;
244    }
245   
246    // check if bcast request is achieved
247
248    for(list<SPendingRequest*>::iterator it=pendingSentChildRequest.begin(); it!=pendingSentChildRequest.end() ; )
249    {
250      MPI_Test(&(*it)->request,&received,&status) ;
251      if (received)
252      {
253        delete *it ;    // free memory
254        it = pendingSentChildRequest.erase(it) ;          // get out of the list
255
256      }
257      else ++it ;
258       
259    }
260  }
261 
262  void CEventScheduler::bcastEvent(const size_t timeLine, const size_t contextHashId, const size_t lev)
263  {
264    SPendingRequest* sentRequest ;
265     
266   
267    for(int i=0; i<nbChild[lev];i++)
268    {
269      sentRequest=new SPendingRequest ;
270      sentRequest->buffer[0]=timeLine ;
271      sentRequest->buffer[1]=contextHashId ;
272      sentRequest->buffer[2]=lev+1 ;
273      MPI_Isend(sentRequest->buffer,3, MPI_UNSIGNED_LONG, child[lev][i], 1, communicator, & sentRequest->request) ;
274      pendingSentChildRequest.push_back(sentRequest) ;
275    }
276  }
277   
278
279}
Note: See TracBrowser for help on using the repository browser.