revise app interation API for better interface
[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     double appWorkStartTimer;
276     /** the amount of application useful work, need app knowledge */
277     double totalAppTime;
278
279     /** The amount of time spent idle since we last reset the counters */
280     double totalIdleTime;
281
282     /* * maximum excution time of a single entry method */
283     double maxEntryMethodTime;
284
285     /** The highest seen memory usage  since we last reset the counters */
286     double memUsage;
287
288     /** The number of entry method invocations since we last reset the counters */
289     long totalEntryMethodInvocations;
290
291     /** The time we last rest the counters */
292     double lastResetTime;
293
294     double phaseEndTime;
295
296     /* * summary data */
297     perfData *currentSummary; 
298
299     vector<timerPair> phasesTimers;
300
301     int currentGroupID;
302     CkArrayIndex currentIndex;
303     map<int, map<CkArrayIndex, double> > ObjectLoadTime;
304
305     // In some programs like Changa, entry methods may be nested, and hence we only want to consider the outermost one
306     int nesting_level;
307
308     TraceAutoPerf(char **argv);
309   
310     //begin/end tracing
311     void traceBegin(void);
312     void traceEnd(void);
313
314
315   // a user event has just occured
316   void userEvent(int eventID);
317   // a pair of begin/end user event has just occured
318   void userBracketEvent(int eventID, double bt, double et);
319   void beginAppWork();
320   void endAppWork();
321   
322   // "creation" of message(s) - message Sends
323   void creation(envelope *, int epIdx, int num=1);
324   void creationMulticast(envelope *, int epIdx, int num=1, int *pelist=NULL);
325   void creationDone(int num=1);
326   
327   void messageRecv(char *env, int pe);
328   
329   void beginExecute(envelope *);
330   void beginExecute(CmiObjId *tid);
331   
332   void beginExecute(
333             envelope* env,
334             int event,   // event type defined in trace-common.h
335                     int msgType, // message type
336                     int ep,      // Charm++ entry point id
337                     int srcPe,   // Which PE originated the call
338                     int ml,      // message size
339                     CmiObjId* idx);    // index
340
341   
342   void beginExecute(
343                     int event,   // event type defined in trace-common.h
344                     int msgType, // message type
345                     int ep,      // Charm++ entry point id
346                     int srcPe,   // Which PE originated the call
347                     int ml,      // message size
348                     CmiObjId* idx);    // index
349   void endExecute(void);
350   
351   // begin/end idle time for this pe
352   void beginIdle(double curWallTime);
353   void endIdle(double curWallTime);
354   
355   // begin/end of execution
356   void beginComputation(void);
357   void endComputation(void);
358   
359   /* Memory tracing */
360   void malloc(void *where, int size, void **stack, int stackSize);
361   void free(void *where, int size);
362   
363   // do any clean-up necessary for tracing
364   void traceClose();
365
366   // ==================================================================
367   /** reset the idle time and entry method execution time accumulators */
368   void resetTimings();
369   /** Reset the idle, overhead, and memory measurements */
370   void resetAll();
371
372   /*  mark one phase (to record begin and end timer ) */
373   void markStep();
374
375   /** Fraction of the time spent idle since resetting the counters */
376   inline double checkIdleRatioDuringIdle() 
377   {
378       if(lastEvent == BEGIN_IDLE)
379           return (totalIdleTime + TraceTimer() - lastBeginIdle ) / ( TraceTimer()-lastResetTime);  
380       else
381           return (totalIdleTime) / ( TraceTimer()-lastResetTime);  
382
383   }
384
385   inline double idleRatio(){
386       if(lastEvent == BEGIN_IDLE)
387           totalIdleTime += (TraceTimer() - lastBeginIdle);
388       return (totalIdleTime) / totalTraceTime();
389   }
390
391   inline double idleTime()
392   {
393       if(lastEvent == BEGIN_IDLE)
394           totalIdleTime += (TraceTimer() - lastBeginIdle);
395       return totalIdleTime;
396   }
397
398   inline double untracedTime(){
399     if(whenStoppedTracing <= 0){
400       return totalUntracedTime;     
401     } else {
402       return totalUntracedTime + (phaseEndTime -whenStoppedTracing);
403     }
404
405   }
406
407   inline double totalTraceTime()
408   {
409       return phaseEndTime - lastResetTime ;
410       //return phaseEndTime - lastResetTime - untracedTime();
411   }
412   /** Fraction of time spent as overhead since resetting the counters */
413   inline double overheadRatio(){
414     double t = totalTraceTime(); 
415     return (t - totalIdleTime - totalEntryMethodTime)/t; 
416   } 
417
418   inline double overheadTime(){
419     double t = totalTraceTime(); 
420     return (t - totalIdleTime - totalEntryMethodTime); 
421   } 
422
423   inline double utilRatio() {
424       if(lastEvent == BEGIN_PROCESSING)
425           totalEntryMethodTime += (TraceTimer() - lastBeginExecuteTime);
426       return totalEntryMethodTime/ totalTraceTime(); 
427   }
428
429   inline double utilTime() {
430       if(lastEvent == BEGIN_PROCESSING)
431           totalEntryMethodTime += (TraceTimer() - lastBeginExecuteTime);
432       return totalEntryMethodTime; 
433   }
434
435   inline double appRatio() {
436       return totalAppTime/ totalTraceTime(); 
437   }
438
439   inline double appTime() {
440       return totalAppTime; 
441   }
442   /** Highest memory usage (in MB) value we've seen since resetting the counters */
443   inline double memoryUsageMB(){
444     return ((double)memUsage) / 1024.0 / 1024.0;
445   }
446
447   /** Determine the average grain size since last reset of counters */
448   inline double grainSize(){
449     return (double)totalEntryMethodTime / totalEntryMethodInvocations;
450   }
451
452   inline double maxGrainSize() {
453     return maxEntryMethodTime;
454   }
455
456   inline long bytesPerEntry() {
457     return currentSummary->numBytes / currentSummary->numMsgs;
458   }
459    
460   inline long numInvocations() {
461       return totalEntryMethodInvocations;
462   }
463
464 #if CMK_HAS_COUNTER_PAPI
465   inline void readPAPI()
466   {
467       if (PAPI_read(CkpvAccess(papiEventSet), CkpvAccess(papiValues)) != PAPI_OK) {
468           CmiAbort("PAPI failed to read at begin execute!\n");
469       }
470   }
471 #endif
472
473   perfData* getSummary()
474   {
475       currentSummary->idleMin = currentSummary->idleMax= idleRatio(); 
476       currentSummary->idleTotalTime = idleTime();
477       currentSummary->utilMin = currentSummary->utilMax = utilRatio(); 
478       currentSummary->utilTotalTime= utilTime();
479       currentSummary->appMin = currentSummary->appMax = appRatio(); 
480       currentSummary->appTotalTime= appTime();
481       currentSummary->overheadMin = currentSummary->overheadMax = overheadRatio();
482       currentSummary->overheadTotalTime = overheadTime();
483       currentSummary->grainsizeAvg = grainSize();
484       currentSummary->grainsizeMax = maxGrainSize();
485       currentSummary->numInvocations = totalEntryMethodInvocations;
486 #if CMK_HAS_COUNTER_PAPI
487       readPAPI();
488       for(int i=0; i<NUMPAPIEVENTS; i++)
489       {
490           currentSummary->papiValues[i] = (CkpvAccess(papiValues)[i] - previous_papiValues[i]);
491       }
492 #endif
493       return currentSummary;
494   }
495
496   void printSummary()
497   {
498       CkPrintf("################\n");
499       CkPrintf("\t-------%d local data idle:util:overhead %f:%f:%f\n", CkMyPe(), currentSummary->idleMin, currentSummary->utilMin, currentSummary->overheadMin);
500       CkPrintf("################\n");
501   }
502 };
503
504
505 TraceAutoPerf *localControlPointTracingInstance();
506
507 #endif
508