source: XIOS/trunk/src/event_scheduler.cpp @ 1638

Last change on this file since 1638 was 1638, checked in by yushan, 3 years ago

dev on ADA

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