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