source: XIOS/dev/branch_openmp/src/event_scheduler.cpp @ 1365

Last change on this file since 1365 was 1365, checked in by yushan, 6 years ago

unify type : MPI_Datatype MPI_Aint

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