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