d3653dade29557680fb2a307ead06b2433466bdc
[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 appMin;
162     double appTotalTime;
163     double appMax;
164
165     double overheadMin;
166     double overheadTotalTime;
167     double overheadMax;
168
169     double mem;
170     
171     double grainsizeAvg;
172     double grainsizeMax;
173     
174     long   numInvocations;
175     
176     // communication related data 
177     long    numMsgs;
178     long    numBytes;
179     double  commTime;
180     double  objLoadMax;
181
182 #if CMK_HAS_COUNTER_PAPI
183     LONG_LONG_PAPI papiValues[NUMPAPIEVENTS];
184 #endif
185     // functions
186     perfData(){}
187 };
188
189
190 typedef struct {
191     double packing;
192     double unpacking;
193
194 } sideSummary_t;
195
196 typedef struct{
197     double beginTimer;
198     double endTimer;
199 }timerPair;
200
201 //map<int, double> ObjectLoadTime;
202
203 class TraceAutoPerfInit : public Chare {
204
205 public:
206     TraceAutoPerfInit(CkArgMsg*);
207
208     TraceAutoPerfInit(CkMigrateMessage *m):Chare(m) {}
209 };
210
211
212 class TraceAutoPerfBOC : public CBase_TraceAutoPerfBOC {
213 private:
214     int         lastAnalyzeStep;   
215     double      startStepTimer;
216 public:
217     TraceAutoPerfBOC() {
218         startStepTimer = CkWallTimer();
219         lastAnalyzeStep = 0;
220     }
221
222     TraceAutoPerfBOC(CkMigrateMessage *m) : CBase_TraceAutoPerfBOC(m) {};
223
224     void pup(PUP::er &p)
225     {
226         CBase_TraceAutoPerfBOC::pup(p);
227     }
228
229     void setAutoPerfDoneCallback(CkCallback cb, bool frameworkShouldAdvancePhase); 
230     void timeStep(int);
231     void getPerfData(int reductionPE, CkCallback cb);
232     void globalPerfAnalyze(CkReductionMsg *msg);
233     void localPerfQuery();
234     void generatePerfModel();
235
236 };
237
238 //SMP mode
239 class TraceNodeAutoPerfBOC : public CBase_TraceNodeAutoPerfBOC {
240
241 public:
242     TraceNodeAutoPerfBOC(void) {}
243     TraceNodeAutoPerfBOC(CkMigrateMessage *m) : CBase_TraceNodeAutoPerfBOC(m) {};
244
245     void timeStep(int);
246     void getPerfData(int reductionPE, CkCallback cb);
247
248 };
249
250
251 class TraceAutoPerf : public Trace {
252
253     friend class TraceAutoPerfBOC;
254
255 public:
256
257 #if CMK_HAS_COUNTER_PAPI
258     LONG_LONG_PAPI previous_papiValues[NUMPAPIEVENTS];
259 #endif
260     double  lastBeginExecuteTime;
261     int     lastbeginMessageSize;
262     int     lastEvent;
263     /** The start of the idle region */
264     double  lastBeginIdle;
265
266     /** Amount of time spent so far in untraced regions */
267     double totalUntracedTime;
268
269     /** When tracing was suspended (0 if not currently suspended) */
270     double whenStoppedTracing;
271
272     /** The amount of time spent executing entry methods since we last reset the counters */
273     double totalEntryMethodTime;
274
275     /** the amount of application useful work, need app knowledge */
276     double totalAppTime;
277
278     /** The amount of time spent idle since we last reset the counters */
279     double totalIdleTime;
280
281     /* * maximum excution time of a single entry method */
282     double maxEntryMethodTime;
283
284     /** The highest seen memory usage  since we last reset the counters */
285     double memUsage;
286
287     /** The number of entry method invocations since we last reset the counters */
288     long totalEntryMethodInvocations;
289
290     /** The time we last rest the counters */
291     double lastResetTime;
292
293     double phaseEndTime;
294
295     /* * summary data */
296     perfData *currentSummary; 
297
298     vector<timerPair> phasesTimers;
299
300     int currentGroupID;
301     CkArrayIndex currentIndex;
302     map<int, map<CkArrayIndex, double> > ObjectLoadTime;
303
304     // In some programs like Changa, entry methods may be nested, and hence we only want to consider the outermost one
305     int nesting_level;
306
307     TraceAutoPerf(char **argv);
308   
309     //begin/end tracing
310     void traceBegin(void);
311     void traceEnd(void);
312
313
314   // a user event has just occured
315   void userEvent(int eventID);
316   // a pair of begin/end user event has just occured
317   void userBracketEvent(int eventID, double bt, double et);
318   void appWork(int eventID, double bt, double et);
319   
320   // "creation" of message(s) - message Sends
321   void creation(envelope *, int epIdx, int num=1);
322   void creationMulticast(envelope *, int epIdx, int num=1, int *pelist=NULL);
323   void creationDone(int num=1);
324   
325   void messageRecv(char *env, int pe);
326   
327   void beginExecute(envelope *);
328   void beginExecute(CmiObjId *tid);
329   
330   void beginExecute(
331             envelope* env,
332             int event,   // event type defined in trace-common.h
333                     int msgType, // message type
334                     int ep,      // Charm++ entry point id
335                     int srcPe,   // Which PE originated the call
336                     int ml,      // message size
337                     CmiObjId* idx);    // index
338
339   
340   void beginExecute(
341                     int event,   // event type defined in trace-common.h
342                     int msgType, // message type
343                     int ep,      // Charm++ entry point id
344                     int srcPe,   // Which PE originated the call
345                     int ml,      // message size
346                     CmiObjId* idx);    // index
347   void endExecute(void);
348   
349   // begin/end idle time for this pe
350   void beginIdle(double curWallTime);
351   void endIdle(double curWallTime);
352   
353   // begin/end of execution
354   void beginComputation(void);
355   void endComputation(void);
356   
357   /* Memory tracing */
358   void malloc(void *where, int size, void **stack, int stackSize);
359   void free(void *where, int size);
360   
361   // do any clean-up necessary for tracing
362   void traceClose();
363
364   // ==================================================================
365   /** reset the idle time and entry method execution time accumulators */
366   void resetTimings();
367   /** Reset the idle, overhead, and memory measurements */
368   void resetAll();
369
370   /*  mark one phase (to record begin and end timer ) */
371   void markStep();
372
373   /** Fraction of the time spent idle since resetting the counters */
374   inline double checkIdleRatioDuringIdle() 
375   {
376       if(lastEvent == BEGIN_IDLE)
377           return (totalIdleTime + TraceTimer() - lastBeginIdle ) / ( TraceTimer()-lastResetTime);  
378       else
379           return (totalIdleTime) / ( TraceTimer()-lastResetTime);  
380
381   }
382
383   inline double idleRatio(){
384       if(lastEvent == BEGIN_IDLE)
385           totalIdleTime += (TraceTimer() - lastBeginIdle);
386       return (totalIdleTime) / totalTraceTime();
387   }
388
389   inline double idleTime()
390   {
391       if(lastEvent == BEGIN_IDLE)
392           totalIdleTime += (TraceTimer() - lastBeginIdle);
393       return totalIdleTime;
394   }
395
396   inline double untracedTime(){
397     if(whenStoppedTracing <= 0){
398       return totalUntracedTime;     
399     } else {
400       return totalUntracedTime + (phaseEndTime -whenStoppedTracing);
401     }
402
403   }
404
405   inline double totalTraceTime()
406   {
407       return phaseEndTime - lastResetTime ;
408       //return phaseEndTime - lastResetTime - untracedTime();
409   }
410   /** Fraction of time spent as overhead since resetting the counters */
411   inline double overheadRatio(){
412     double t = totalTraceTime(); 
413     return (t - totalIdleTime - totalEntryMethodTime)/t; 
414   } 
415
416   inline double overheadTime(){
417     double t = totalTraceTime(); 
418     return (t - totalIdleTime - totalEntryMethodTime); 
419   } 
420
421   inline double utilRatio() {
422       if(lastEvent == BEGIN_PROCESSING)
423           totalEntryMethodTime += (TraceTimer() - lastBeginExecuteTime);
424       return totalEntryMethodTime/ totalTraceTime(); 
425   }
426
427   inline double utilTime() {
428       if(lastEvent == BEGIN_PROCESSING)
429           totalEntryMethodTime += (TraceTimer() - lastBeginExecuteTime);
430       return totalEntryMethodTime; 
431   }
432
433   inline double appRatio() {
434       return totalAppTime/ totalTraceTime(); 
435   }
436
437   inline double appTime() {
438       return totalAppTime; 
439   }
440   /** Highest memory usage (in MB) value we've seen since resetting the counters */
441   inline double memoryUsageMB(){
442     return ((double)memUsage) / 1024.0 / 1024.0;
443   }
444
445   /** Determine the average grain size since last reset of counters */
446   inline double grainSize(){
447     return (double)totalEntryMethodTime / totalEntryMethodInvocations;
448   }
449
450   inline double maxGrainSize() {
451     return maxEntryMethodTime;
452   }
453
454   inline long bytesPerEntry() {
455     return currentSummary->numBytes / currentSummary->numMsgs;
456   }
457    
458   inline long numInvocations() {
459       return totalEntryMethodInvocations;
460   }
461
462 #if CMK_HAS_COUNTER_PAPI
463   inline void readPAPI()
464   {
465       if (PAPI_read(CkpvAccess(papiEventSet), CkpvAccess(papiValues)) != PAPI_OK) {
466           CmiAbort("PAPI failed to read at begin execute!\n");
467       }
468   }
469 #endif
470
471   perfData* getSummary()
472   {
473       currentSummary->idleMin = currentSummary->idleMax= idleRatio(); 
474       currentSummary->idleTotalTime = idleTime();
475       currentSummary->utilMin = currentSummary->utilMax = utilRatio(); 
476       currentSummary->utilTotalTime= utilTime();
477       currentSummary->appMin = currentSummary->appMax = appRatio(); 
478       currentSummary->appTotalTime= appTime();
479       currentSummary->overheadMin = currentSummary->overheadMax = overheadRatio();
480       currentSummary->overheadTotalTime = overheadTime();
481       currentSummary->grainsizeAvg = grainSize();
482       currentSummary->grainsizeMax = maxGrainSize();
483       currentSummary->numInvocations = totalEntryMethodInvocations;
484 #if CMK_HAS_COUNTER_PAPI
485       readPAPI();
486       for(int i=0; i<NUMPAPIEVENTS; i++)
487       {
488           currentSummary->papiValues[i] = (CkpvAccess(papiValues)[i] - previous_papiValues[i]);
489       }
490 #endif
491       return currentSummary;
492   }
493
494   void printSummary()
495   {
496       CkPrintf("################\n");
497       CkPrintf("\t-------%d local data idle:util:overhead %f:%f:%f\n", CkMyPe(), currentSummary->idleMin, currentSummary->utilMin, currentSummary->overheadMin);
498       CkPrintf("################\n");
499   }
500 };
501
502
503 TraceAutoPerf *localControlPointTracingInstance();
504
505 #endif
506