OpenAtom  Version1.5a
TimeKeeper.h
Go to the documentation of this file.
1 #include "charm++.h"
2 
3 #ifndef TimeKeeper_h
4 #define TimeKeeper_h
5 
6 /*
7  * HPM will instrument one step using BG/P UPC performance counters.
8  * To use it, build libhpm.a in src_charm_driver/utilities/
9  * copy it someplace in your lib search path and add -lhpm to link line
10  * Also add -L/bgsys/drivers/ppcfloor/runtime -lSPI.cna to link line.
11  * DO NOT use /soft/apps/UPC/lib/libhpm.a it uses MPI and will
12  * cause you a lot of grief.
13  */
14 #if USE_HPM
15 extern "C" void HPM_Init(int);
16 extern "C" void HPM_Start(char *label,int);
17 extern "C" void HPM_Stop(char *label,int);
18 extern "C" void HPM_Print(int,int);
19 #endif
20 
21 //////////////////////////////////////////////////////////////////////////////
22 //////////////////////////////////////////////////////////////////////////////
23 //////////////////////////////////////////////////////////////////////////////
24 /** \file TimeKeeper.h
25  *
26  * A place to collect substep times. Each participating chare will register
27  * with the timekeeper on processor 0. Giving its name and getting the next
28  * available timekeeper id. Also handles performance counters and projections
29  * start/stop.
30  *
31  * Then at the beginning of its notional step every chare will contribute its
32  * start time to a minimum reduction. At the end of its notional step each
33  * chare will contribute its end time to a maximum reduction. The timekeeper
34  * will print out the delta time and name for each substep when it has the min
35  * and max.
36  *
37  * HPM will instrument one step using BG/P UPC performance counters. To use
38  * it, build libhpm.a in src_charm_driver/utilities/ copy it someplace in your
39  * lib search path and add -lhpm to link line Also add
40  * -L/bgsys/drivers/ppcfloor/runtime -lSPI.cna to link line. DO NOT use
41  * /soft/apps/UPC/lib/libhpm.a it uses MPI and will cause you a lot of grief.
42  */
43 
44 #include <vector>
45 #include <string>
46 #include "TopoManager.h"
47 
48 #if USE_HPM
49 extern "C" void HPM_Init(int);
50 extern "C" void HPM_Start(char *label,int);
51 extern "C" void HPM_Stop(char *label,int);
52 extern "C" void HPM_Print(int,int);
53 #endif
54 
55 extern Config config;
56 extern int TimeKeeperID;
57 extern std::vector <std::string> TimeKeeperNames;
58 
59 static int keeperRegister(std::string name)
60 {
61  if(config.useTimeKeeper)
62  {
63  TimeKeeperNames.push_back(name);
64  return(TimeKeeperID++);
65  }
66  else
67  { //disable all timers
68  return(-1);
69  }
70 }
71 
72 class TimeKeeper : public Group
73 {
74  public:
75  double *beginTime;
76  int HPMCounter;
77  int HPMEndCounter;
78  int PRJCounter;
79  int local_rank;
80  TimeKeeper(){
81  HPMCounter=-1;
82  HPMEndCounter=0;
83  PRJCounter=0;
84 #if USE_HPM
85  TopoManager *topoMgr = new TopoManager();
86  int x,y,z;
87  topoMgr->rankToCoordinates(CkMyPe(),x,y,z,local_rank);
88  delete topoMgr;
89 #endif
90  }
91 
92  void startTrace()
93  {
94 #if CMK_TRACE_ENABLED
95  if(PRJCounter++==0)
96  {
97  traceBegin();
98  // CkPrintf("[%d] trace begun \n",CkMyPe());
99  }
100 #endif
101  }
102 
103  void stopTrace()
104  {
105 #if CMK_TRACE_ENABLED
106  if(--PRJCounter==0)
107  {
108  traceEnd();
109  // CkPrintf("[%d] trace ended \n",CkMyPe());
110  }
111 #endif
112  }
113 
114 #if USE_HPM
115  void initHPM(){
116  if(HPMCounter==-1)
117  {
118  if(CkMyPe()==0)
119  CkPrintf("[%d] HPM_Init\n",CkMyPe());
120  HPM_Init(local_rank);
121  HPMCounter=0;
122  }
123  }
124  void startHPM(char *string){
125  if(HPMCounter++==0)
126  {
127  if(CkMyPe()==0)
128  CkPrintf("[%d] HPM_Start\n",CkMyPe());
129  HPM_Start(string, local_rank);
130  }
131  }
132  void stopHPM(char *string)
133  {
134  if(--HPMCounter==0)
135  {
136  if(CkMyPe()==0)
137  CkPrintf("[%d] HPM_Stop\n", CkMyPe());
138  HPM_Stop(string, local_rank);
139  HPMEndCounter=HPMCounter+1;
140  }
141 
142  }
143 
144  void printHPM()
145  {
146  if(--HPMEndCounter==0)
147  {
148  if(CkMyPe()==0)
149  CkPrintf("[%d] HPM_Print\n",CkMyPe());
150  HPM_Print(CkMyPe(), local_rank);
151  }
152 
153  }
154 #endif
155  // the timekeeper phase stuff is really only expected to work on pe 0
156  void init ()
157  {
158  beginTime=new double[TimeKeeperID+1];
159  }
160  void collectStart(CkReductionMsg *msg)
161  {
162  int phase= msg->getUserFlag();
163  CkAssert(phase<TimeKeeperID);
164  CkAssert(phase>=0);
165  beginTime[phase] = *((double *)msg->getData());
166  // CkPrintf("Phase %s start %.10g\n",TimeKeeperNames[phase].c_str(), beginTime[phase]);
167  delete msg;
168  }
169 
170  // we assume sanity and do our printing when each max arrives
171  void collectEnd(CkReductionMsg *msg)
172  {
173  int phase = msg->getUserFlag();
174  CkAssert(phase<TimeKeeperID);
175  double endTime = *((double *)msg->getData());
176  delete msg;
177  // CkPrintf("Phase %s start %.10g end %.10g duration %.10g\n",TimeKeeperNames[phase].c_str(),beginTime[phase],endTime, endTime-beginTime[phase]);
178  CkPrintf("Phase %s duration %.10g\n",TimeKeeperNames[phase].c_str(), endTime-beginTime[phase]);
179  }
180 };
181 #endif