add auto performance analysis tracemode, currently it performs post moterm analysis
[charm.git] / src / ck-tune / trace-autoPerf.h
1 #ifndef  TRACE__AUTOPERF__H__
2 #define  TRACE__AUTOPERF__H__
3 #define _VERBOSE_H
4
5 #include <stdio.h>
6 #include <errno.h>
7 #include "charm++.h"
8 #include "trace.h"
9 #include "envelope.h"
10 #include "register.h"
11 #include "trace-common.h"
12 #include "TraceAutoPerf.decl.h"
13 #include "trace-projections.h"
14 #include <vector>
15 #include <map>
16 #include <list>
17
18
19 using namespace std;
20
21 extern CkGroupID traceAutoPerfGID;
22 extern CProxy_TraceAutoPerfBOC autoPerfProxy;
23 extern CProxy_TraceNodeAutoPerfBOC autoPerfNodeProxy;
24 // class to store performance data on each PE
25
26
27 class perfMetric
28 {
29 public:
30     double timeStep;
31     double utilPercentage;
32     double overheadPercentage;
33     double idlePercentage;
34
35     perfMetric(double step, double util, double idle, double overhead)
36     {
37         timeStep = step;
38         idlePercentage = idle;
39         overheadPercentage = overhead;
40         utilPercentage = util;
41     }
42 };
43
44
45 class savedPerfDatabase
46 {
47 private:
48     std::list<perfMetric*> perfList;
49     perfMetric *previous;
50     perfMetric *current;
51
52 public:
53     savedPerfDatabase() {}
54
55     void insert(double timestep, double idleP, double utilP, double overheadP) {
56         if(perfList.size() ==0)
57         {
58             previous = current= new perfMetric(timestep, utilP, idleP, overheadP);
59         }
60         else if(perfList.size() < 10)
61         {
62             //only save 10 iterations to save memory
63             previous = (perfMetric*)perfList.back();
64             current = new perfMetric(timestep, utilP, idleP, overheadP);
65         }
66         else
67         {
68             previous = (perfMetric*)perfList.back();
69             current = (perfMetric*) perfList.front();
70             perfList.pop_front();
71             current->timeStep = timestep;
72             current->utilPercentage = utilP;
73             current->idlePercentage = idleP;
74             current->overheadPercentage = overheadP;
75         }
76         perfList.push_back(current);
77     }
78
79     void getData(int i)
80     {
81
82     }
83
84     bool timeStepLonger()
85     {
86         return current->timeStep > previous->timeStep;
87     }
88
89     double getCurrentTimestep()
90     {
91         return current->timeStep; 
92     }
93
94     double getPreviousTimestep()
95     {
96         return previous->timeStep;
97     }
98
99     double getTimestepRatio()
100     {
101         CkPrintf("Time step changes from %f to %f \n", previous->timeStep, current->timeStep);
102         return current->timeStep/previous->timeStep;
103     }
104     
105     double getUtilRatio()
106     {
107        return current->utilPercentage/ previous->utilPercentage; 
108     }
109
110     double getCurrentIdlePercentage()
111     {
112         return current->idlePercentage;
113     }
114     
115     double getPreviousIdlePercentage()
116     {
117         return previous->idlePercentage;
118     }
119
120     double getIdleRatio()
121     {
122         return  current->idlePercentage/previous->idlePercentage;
123     }
124     double getCurrentOverheadPercentage()
125     {
126         return current->overheadPercentage;
127     }
128     
129     double getPreviousOverheadPercentage()
130     {
131         return previous->overheadPercentage;
132     }
133     
134     double getOverheadRatio()
135     {
136         return current->overheadPercentage/previous->overheadPercentage;
137     }
138
139     void getAllTimeSteps(double *y)
140     {
141        int i=0; 
142
143        for(std::list<perfMetric*>::iterator it=perfList.begin(); it != perfList.end(); it++,i++)
144        {
145            y[i] = (*it)->timeStep;
146        }
147     }
148 };
149
150
151 class perfData 
152 {
153 public:
154     double idleMin;
155     double idleTotalTime;
156     double idleMax;
157     
158     double utilMin;
159     double utilTotalTime;
160     double utilMax;
161    
162     double overheadMin;
163     double overheadTotalTime;
164     double overheadMax;
165
166     double mem;
167     
168     double grainsizeAvg;
169     double grainsizeMax;
170     
171     long   numInvocations;
172     
173     // communication related data 
174     long    numMsgs;
175     long    numBytes;
176     double  commTime;
177     double  objLoadMax;
178
179     // functions
180     perfData(){}
181 };
182
183
184 typedef struct {
185     double packing;
186     double unpacking;
187
188 } sideSummary_t;
189
190 typedef struct{
191     double beginTimer;
192     double endTimer;
193 }timerPair;
194
195 //map<int, double> ObjectLoadTime;
196
197 class TraceAutoPerfInit : public Chare {
198
199 public:
200     TraceAutoPerfInit(CkArgMsg*);
201
202     TraceAutoPerfInit(CkMigrateMessage *m):Chare(m) {}
203 };
204
205
206 class TraceAutoPerfBOC : public CBase_TraceAutoPerfBOC {
207 private:
208     int         lastAnalyzeStep;   
209     double      startStepTimer;
210 public:
211     TraceAutoPerfBOC() {
212         startStepTimer = CkWallTimer();
213         lastAnalyzeStep = 0;
214     }
215
216     TraceAutoPerfBOC(CkMigrateMessage *m) : CBase_TraceAutoPerfBOC(m) {};
217
218     void pup(PUP::er &p)
219     {
220         CBase_TraceAutoPerfBOC::pup(p);
221     }
222
223     void setAutoPerfDoneCallback(CkCallback cb, bool frameworkShouldAdvancePhase); 
224     void timeStep(int);
225     void getPerfData(int reductionPE, CkCallback cb);
226     void globalPerfAnalyze(CkReductionMsg *msg);
227     void localPerfQuery();
228     void generatePerfModel();
229
230 };
231
232 //SMP mode
233 class TraceNodeAutoPerfBOC : public CBase_TraceNodeAutoPerfBOC {
234
235 public:
236     TraceNodeAutoPerfBOC(void) {}
237     TraceNodeAutoPerfBOC(CkMigrateMessage *m) : CBase_TraceNodeAutoPerfBOC(m) {};
238
239     void timeStep(int);
240     void getPerfData(int reductionPE, CkCallback cb);
241
242 };
243
244
245 class TraceAutoPerf : public Trace {
246
247     friend class TraceAutoPerfBOC;
248
249 public:
250
251     double  lastBeginExecuteTime;
252     int     lastbeginMessageSize;
253     int     lastEvent;
254     /** The start of the idle region */
255     double  lastBeginIdle;
256
257     /** Amount of time spent so far in untraced regions */
258     double totalUntracedTime;
259
260     /** When tracing was suspended (0 if not currently suspended) */
261     double whenStoppedTracing;
262
263     /** The amount of time spent executing entry methods since we last reset the counters */
264     double totalEntryMethodTime;
265
266     /** The amount of time spent idle since we last reset the counters */
267     double totalIdleTime;
268
269     /* * maximum excution time of a single entry method */
270     double maxEntryMethodTime;
271
272     /** The highest seen memory usage  since we last reset the counters */
273     double memUsage;
274
275     /** The number of entry method invocations since we last reset the counters */
276     long totalEntryMethodInvocations;
277
278     /** The time we last rest the counters */
279     double lastResetTime;
280
281     double phaseEndTime;
282
283     /* * summary data */
284     perfData *currentSummary; 
285
286     vector<timerPair> phasesTimers;
287
288     int currentGroupID;
289     CkArrayIndex currentIndex;
290     map<int, map<CkArrayIndex, double> > ObjectLoadTime;
291
292     // In some programs like Changa, entry methods may be nested, and hence we only want to consider the outermost one
293     int nesting_level;
294
295     TraceAutoPerf(char **argv);
296   
297     //begin/end tracing
298     void traceBegin(void);
299     void traceEnd(void);
300
301
302   // a user event has just occured
303   void userEvent(int eventID);
304   // a pair of begin/end user event has just occured
305   void userBracketEvent(int eventID, double bt, double et);
306   
307   // "creation" of message(s) - message Sends
308   void creation(envelope *, int epIdx, int num=1);
309   void creationMulticast(envelope *, int epIdx, int num=1, int *pelist=NULL);
310   void creationDone(int num=1);
311   
312   void messageRecv(char *env, int pe);
313   
314   void beginExecute(envelope *);
315   void beginExecute(CmiObjId *tid);
316   
317   void beginExecute(
318             envelope* env,
319             int event,   // event type defined in trace-common.h
320                     int msgType, // message type
321                     int ep,      // Charm++ entry point id
322                     int srcPe,   // Which PE originated the call
323                     int ml,      // message size
324                     CmiObjId* idx);    // index
325
326   
327   void beginExecute(
328                     int event,   // event type defined in trace-common.h
329                     int msgType, // message type
330                     int ep,      // Charm++ entry point id
331                     int srcPe,   // Which PE originated the call
332                     int ml,      // message size
333                     CmiObjId* idx);    // index
334   void endExecute(void);
335   
336   // begin/end idle time for this pe
337   void beginIdle(double curWallTime);
338   void endIdle(double curWallTime);
339   
340   // begin/end of execution
341   void beginComputation(void);
342   void endComputation(void);
343   
344   /* Memory tracing */
345   void malloc(void *where, int size, void **stack, int stackSize);
346   void free(void *where, int size);
347   
348   // do any clean-up necessary for tracing
349   void traceClose();
350
351   // ==================================================================
352   /** reset the idle time and entry method execution time accumulators */
353   void resetTimings();
354   /** Reset the idle, overhead, and memory measurements */
355   void resetAll();
356
357   /*  mark one phase (to record begin and end timer ) */
358   void markStep();
359
360   /** Fraction of the time spent idle since resetting the counters */
361   inline double checkIdleRatioDuringIdle() 
362   {
363       if(lastEvent == BEGIN_IDLE)
364           return (totalIdleTime + TraceTimer() - lastBeginIdle ) / ( TraceTimer()-lastResetTime);  
365       else
366           return (totalIdleTime) / ( TraceTimer()-lastResetTime);  
367
368   }
369
370   inline double idleRatio(){
371       if(lastEvent == BEGIN_IDLE)
372           totalIdleTime += (TraceTimer() - lastBeginIdle);
373       return (totalIdleTime) / totalTraceTime();
374   }
375
376   inline double idleTime()
377   {
378       if(lastEvent == BEGIN_IDLE)
379           totalIdleTime += (TraceTimer() - lastBeginIdle);
380       return totalIdleTime;
381   }
382
383   inline double untracedTime(){
384     if(whenStoppedTracing <= 0){
385       return totalUntracedTime;     
386     } else {
387       return totalUntracedTime + (phaseEndTime -whenStoppedTracing);
388     }
389
390   }
391
392   inline double totalTraceTime()
393   {
394       return phaseEndTime - lastResetTime ;
395       //return phaseEndTime - lastResetTime - untracedTime();
396   }
397   /** Fraction of time spent as overhead since resetting the counters */
398   inline double overheadRatio(){
399     double t = totalTraceTime(); 
400     return (t - totalIdleTime - totalEntryMethodTime)/t; 
401   } 
402
403   inline double overheadTime(){
404     double t = totalTraceTime(); 
405     return (t - totalIdleTime - totalEntryMethodTime); 
406   } 
407
408   inline double utilRatio() {
409       if(lastEvent == BEGIN_PROCESSING)
410           totalEntryMethodTime += (TraceTimer() - lastBeginExecuteTime);
411       return totalEntryMethodTime/ totalTraceTime(); 
412   }
413
414   inline double utilTime() {
415       if(lastEvent == BEGIN_PROCESSING)
416           totalEntryMethodTime += (TraceTimer() - lastBeginExecuteTime);
417       return totalEntryMethodTime; 
418   }
419   /** Highest memory usage (in MB) value we've seen since resetting the counters */
420   inline double memoryUsageMB(){
421     return ((double)memUsage) / 1024.0 / 1024.0;
422   }
423
424   /** Determine the average grain size since last reset of counters */
425   inline double grainSize(){
426     return (double)totalEntryMethodTime / totalEntryMethodInvocations;
427   }
428
429   inline double maxGrainSize() {
430     return maxEntryMethodTime;
431   }
432
433   inline long bytesPerEntry() {
434     return currentSummary->numBytes / currentSummary->numMsgs;
435   }
436    
437   inline long numInvocations() {
438       return totalEntryMethodInvocations;
439   }
440
441   perfData* getSummary()
442   {
443       currentSummary->idleMin = currentSummary->idleMax= idleRatio(); 
444       currentSummary->idleTotalTime = idleTime();
445       currentSummary->utilMin = currentSummary->utilMax = utilRatio(); 
446       currentSummary->utilTotalTime= utilTime();
447       currentSummary->overheadMin = currentSummary->overheadMax = overheadRatio();
448       currentSummary->overheadTotalTime = overheadTime();
449       currentSummary->grainsizeAvg = grainSize();
450       currentSummary->grainsizeMax = maxGrainSize();
451       currentSummary->numInvocations = totalEntryMethodInvocations;
452       return currentSummary;
453   }
454
455   void printSummary()
456   {
457       CkPrintf("################\n");
458       CkPrintf("\t-------%d local data idle:util:overhead %f:%f:%f\n", CkMyPe(), currentSummary->idleMin, currentSummary->utilMin, currentSummary->overheadMin);
459       CkPrintf("################\n");
460   }
461 };
462
463
464 TraceAutoPerf *localControlPointTracingInstance();
465
466 #endif
467