merge projections and autoperf to use same PAPI init functions
[charm.git] / src / ck-perf / trace-projections.h
1 /**
2  * \addtogroup CkPerf
3 */
4 /*@{*/
5
6 #ifndef _PROJECTIONS_H
7 #define _PROJECTIONS_H
8
9 #include <stdio.h>
10 #include <errno.h>
11 #include <unistd.h>
12
13 #include "trace.h"
14 #include "trace-common.h"
15 #include "ckhashtable.h"
16
17 #if CMK_HAS_COUNTER_PAPI
18 #include <papi.h>
19 #ifdef USE_SPP_PAPI
20 #define NUMPAPIEVENTS 6
21 #else
22 #define NUMPAPIEVENTS 2
23 #endif
24 #endif
25
26 #if CMK_PROJECTIONS_USE_ZLIB
27 #include <zlib.h>
28 #endif
29
30 #include "pup.h"
31
32 #define PROJECTION_VERSION  "7.0"
33
34 #define PROJ_ANALYSIS 1
35
36 // Macro to make projections check for errors before an fprintf succeeds.
37 #define CheckAndFPrintF(f,string,data) \
38 do { \
39   int result = fprintf(f,string,data); \
40   if (result == -1) { \
41     CmiAbort("Projections I/O error!"); \
42   } \
43 } while(false)
44
45 /// a log entry in trace projection
46 class LogEntry {
47   public:
48     double time;
49     double endTime; // Should be used for all bracketed events. Currently only used for bracketed user supplied note
50     double cputime;
51     double recvTime;
52     int event;
53     int pe;
54     unsigned short mIdx;
55     unsigned short eIdx;
56     int msglen;
57     CmiObjId   id;
58     int numpes;
59     int *pes;
60     int userSuppliedData;
61     char *userSuppliedNote;
62     unsigned long memUsage;
63
64     // this is taken out so as to provide a placeholder value for non-PAPI
65     // versions (whose value is *always* zero).
66     //int numPapiEvents;
67 #if CMK_HAS_COUNTER_PAPI
68     LONG_LONG_PAPI papiValues[NUMPAPIEVENTS];
69 #endif
70     unsigned char type; 
71     char *fName;
72     int flen;
73
74   public:
75     
76     LogEntry() {
77       fName=NULL;flen=0;pes=NULL;numpes=0;userSuppliedNote = NULL;
78     }
79
80     LogEntry(double tm, unsigned char t, unsigned short m=0, 
81              unsigned short e=0, int ev=0, int p=0, int ml=0, 
82              CmiObjId *d=NULL, double rt=0., double cputm=0., int numPe=0) {
83       type = t; mIdx = m; eIdx = e; event = ev; pe = p; 
84       time = tm; msglen = ml;
85       if (d) id = *d; else {id.id[0]=id.id[1]=id.id[2]=id.id[3]=0; };
86       recvTime = rt; cputime = cputm;
87       // initialize for papi as well as non papi versions.
88 #if CMK_HAS_COUNTER_PAPI
89       //numPapiEvents = NUMPAPIEVENTS;
90 #else
91       //numPapiEvents = 0;
92 #endif
93       userSuppliedNote = NULL;
94       fName = NULL;
95       flen=0;
96       pes=NULL;
97       numpes=numPe;
98     }
99
100     LogEntry(double _time,unsigned char _type,unsigned short _funcID,
101              int _lineNum,char *_fileName){
102       time = _time;
103       type = _type;
104       mIdx = _funcID;
105       event = _lineNum;
106       userSuppliedNote = NULL;      
107       pes=NULL;
108       numpes=0;
109       setFName(_fileName);
110     }
111
112     // Constructor for User Supplied Data
113     LogEntry(double _time,unsigned char _type, int value,
114              int _lineNum,char *_fileName){
115       time = _time;
116       type = _type;
117       userSuppliedData = value;
118       userSuppliedNote = NULL;
119       pes=NULL;
120       numpes=0;
121       setFName(_fileName);
122     }
123
124     // Constructor for User Supplied Data
125     LogEntry(double _time,unsigned char _type, char* note,
126              int _lineNum,char *_fileName){
127       time = _time;
128       type = _type;
129       pes=NULL;
130       numpes=0;
131       setFName(_fileName);
132       if(note != NULL)
133         setUserSuppliedNote(note);
134     }
135
136
137    // Constructor for bracketed user supplied note
138     LogEntry(double bt, double et, unsigned char _type, char *note, int eventID){
139       time = bt;
140       endTime = et;
141       type = _type;
142       pes=NULL;
143       numpes=0;
144       event = eventID;
145       if(note != NULL)
146         setUserSuppliedNote(note);
147     }
148
149
150     // Constructor for multicast data
151     LogEntry(double tm, unsigned short m, unsigned short e, int ev, int p,
152              int ml, CmiObjId *d, double rt, int numPe, int *pelist){
153
154       type = CREATION_MULTICAST; 
155       mIdx = m; 
156       eIdx = e; 
157       event = ev; 
158       pe = p; 
159       time = tm; 
160       msglen = ml;
161       
162       if (d) id = *d; else {id.id[0]=id.id[1]=id.id[2]=id.id[3]=-1; };
163       recvTime = rt; 
164       numpes = numPe;
165       userSuppliedNote = NULL;
166       if (pelist != NULL) {
167         pes = new int[numPe];
168         for (int i=0; i<numPe; i++) {
169           pes[i] = pelist[i];
170         }
171       } else {
172         pes= NULL;
173       }
174
175     }
176
177
178     void setFName(char *_fileName){
179       if(_fileName == NULL){
180         fName = NULL;
181         flen = 0;
182       }else{
183         fName = new char[strlen(_fileName)+2];
184         fName[0] = ' ';
185         memcpy(fName+1,_fileName,strlen(_fileName)+1);
186         flen = strlen(fName)+1;
187       } 
188     }
189
190     // complementary function for adding papi data
191     void addPapi(LONG_LONG_PAPI *papiVals){
192 #if CMK_HAS_COUNTER_PAPI
193         memcpy(papiValues, papiVals, sizeof(LONG_LONG_PAPI)*NUMPAPIEVENTS);
194 #endif
195     }
196    
197     void setUserSuppliedData(int data){
198       userSuppliedData = data;
199     }
200
201     void setUserSuppliedNote(char *note){
202
203       int length = strlen(note)+1;
204       userSuppliedNote = new char[length];
205       memcpy(userSuppliedNote,note,length);
206       for(int i=0;i<length;i++){
207         if(userSuppliedNote[i] == '\n' || userSuppliedNote[i] == '\r'){
208           userSuppliedNote[i] = ' ';
209         }
210       }
211           
212     }
213         
214
215     /// A constructor for a memory usage record
216     LogEntry(unsigned char _type, double _time, long _memUsage) {
217       time = _time;
218       type = _type;
219       memUsage = _memUsage;
220       fName = NULL;
221       flen = 0;
222       pes=NULL;
223       numpes=0;
224     }
225
226
227     void *operator new(size_t s) {void*ret=malloc(s);_MEMCHECK(ret);return ret;}
228     void *operator new(size_t, void *ptr) { return ptr; }
229     void operator delete(void *ptr) {free(ptr); }
230 #if defined(WIN32) || CMK_MULTIPLE_DELETE
231     void operator delete(void *, void *) { }
232 #endif
233
234     void setNewStartTime(double t) {
235       time -= t;
236       if (endTime>=t) endTime -= t;
237       if (recvTime>=t) recvTime -= t;
238     }
239
240     void pup(PUP::er &p);
241     ~LogEntry(){
242       if (fName) delete [] fName;
243       if (userSuppliedNote) delete [] userSuppliedNote;
244     }
245 };
246
247 class TraceProjections;
248
249 /// log pool in trace projection
250 class LogPool {
251   friend class TraceProjections;
252 #ifdef PROJ_ANALYSIS
253   // The macro is here "just-in-case". Somehow, it seems it is not necessary
254   //   to declare friend classes ahead of time in C++.
255   friend class TraceProjectionsBOC;
256   friend class KMeansBOC;
257 #endif  //PROJ_ANALYSIS
258   friend class controlPointManager;
259   private:
260     bool writeData;
261     int writeSummaryFiles;
262     unsigned int poolSize;
263     unsigned int numEntries;
264     LogEntry *pool;
265     FILE *fp;
266     FILE *deltafp;
267     FILE *stsfp;
268     FILE *rcfp;
269     FILE *topofp;
270     FILE *statisfp;
271     char *fname;
272     char *dfname;
273     char *pgmname;
274     int binary;
275     int nSubdirs;
276 #if CMK_PROJECTIONS_USE_ZLIB
277     gzFile deltazfp;
278     gzFile zfp;
279     int compressed;
280 #endif
281     // **CW** prevTime stores the timestamp of the last event
282     // written out to log. This allows the implementation of
283     // simple delta encoding and should only be used when
284     // writing out logs.
285     double prevTime;
286     double timeErr;
287     double globalStartTime; // used at the end on Pe 0 only
288     double globalEndTime; // used at the end on Pe 0 only
289
290     int numPhases;
291     bool hasFlushed;
292     bool *keepPhase;  // one decision per phase
293
294     int headerWritten;
295     bool fileCreated;
296     void writeHeader();
297
298     // for statistics 
299     double beginComputationTime;
300     double endComputationTime;
301     double statisLastTimer;
302     double statisLastProcessTimer;
303     double statisLastIdleTimer;
304     double statisLastPackTimer;
305     double statisLastUnpackTimer;
306     double statisTotalExecutionTime;
307     double statisTotalIdleTime;
308     double statisTotalPackTime;
309     double statisTotalUnpackTime;
310     long long statisTotalCreationMsgs;
311     long long statisTotalCreationBytes;
312     long long statisTotalMCastMsgs;
313     long long statisTotalMCastBytes;
314     long long statisTotalEnqueueMsgs;
315     long long statisTotalDequeueMsgs;
316     long long statisTotalRecvMsgs;
317     long long statisTotalRecvBytes;
318     long long statisTotalMemAlloc;
319     long long statisTotalMemFree;
320
321
322   public:
323     LogPool(char *pgm);
324     ~LogPool();
325     void setBinary(int b) { binary = b; }
326     void setNumSubdirs(int n) { nSubdirs = n; }
327     void setWriteSummaryFiles(int n) { writeSummaryFiles = n;}
328 #if CMK_PROJECTIONS_USE_ZLIB
329     void setCompressed(int c) { compressed = c; }
330 #endif
331     void createFile(const char *fix="");
332     void createSts(const char *fix="");
333     void createTopo(const char *fix="");
334     void createRC();
335     void openLog(const char *mode);
336     void closeLog(void);
337     void writeLog(void);
338     void write(int writedelta);
339     void writeSts(void);
340     void writeSts(TraceProjections *traceProj);
341     void writeRC(void);
342     void writeTopo();
343     void writeStatis();
344     void initializePhases() {
345       keepPhase = new bool[numPhases];
346       for (int i=0; i<numPhases; i++) {
347         keepPhase[i] = true;
348       }
349     }
350
351     void setAllPhases(bool val) {
352       for (int i=0; i<numPhases; i++) {
353         keepPhase[i] = val;
354       }
355     }
356
357     void add(unsigned char type, unsigned short mIdx, unsigned short eIdx,
358              double time, int event, int pe, int ml=0, CmiObjId* id=0, 
359              double recvT=0.0, double cpuT=0.0, int numPe=0);
360
361     // complementary function to set papi info to current log entry
362     // must be called after an add()
363     void addPapi(LONG_LONG_PAPI *papVals) {
364       pool[numEntries-1].addPapi(papVals);
365     }
366
367         /** add a record for a user supplied piece of data */
368         void addUserSupplied(int data);
369
370         /** add a record for a user supplied piece of data */
371         void addUserSuppliedNote(char *note);
372
373
374         void add(unsigned char type,double time,unsigned short funcID,int lineNum,char *fileName);
375   
376         void addMemoryUsage(unsigned char type,double time,double memUsage);
377         void addUserSuppliedBracketedNote(char *note, int eventID, double bt, double et);
378
379     void addCreationMulticast(unsigned short mIdx,unsigned short eIdx,double time,int event,int pe, int ml=0, CmiObjId* id=0, double recvT=0., int numPe=0, int *pelist=NULL);
380     void flushLogBuffer();
381     void postProcessLog();
382
383     void setWriteData(bool b){
384       writeData = b;
385     }
386     void modLastEntryTimestamp(double ts);
387
388     void setNewStartTime() {
389       for(UInt i=0; i<numEntries; i++) pool[i].setNewStartTime(globalStartTime);
390     }
391 };
392
393 /*
394         class that represents a key in a CkHashtable with a string as a key
395 */
396 class StrKey {
397         char *str;
398         int len;
399         unsigned int key;
400         public:
401         StrKey(char *_str,int _len){
402                 str = _str;
403                 len = _len;
404                 key = 0;
405                 for(int i=0;i<len;i++){
406                         key += str[i];
407                 }
408         }
409         static CkHashCode staticHash(const void *k,size_t){
410                 return ((StrKey *)k)->key;
411         }
412         static int staticCompare(const void *a,const void *b,size_t){
413                 StrKey *p,*q;
414                 p = (StrKey *)a;
415                 q = (StrKey *)b;
416                 if(p->len != q->len){
417                         return 0;
418                 }
419                 for(int i=0;i<p->len;i++){
420                         if(p->str[i] != q->str[i]){
421                                 return 0;
422                         }
423                 }
424                 return 1;
425         }
426         inline CkHashCode hash() const{
427                 return key;
428         }
429         inline int compare(const StrKey &t) const {
430                 if(len != t.len){
431                         return 0;
432                 }
433                 for(int i=0;i<len;i++){
434                         if(str[i] != t.str[i]){
435                                 return 0;
436                         }       
437                 }
438                 return 1;
439         }
440         inline char *getStr(){
441                 return str;
442         }
443 };
444
445 class NestedEvent {
446  public:
447   int event, msgType, ep, srcPe, ml;
448   CmiObjId *idx;
449   NestedEvent() {}
450   NestedEvent(int _event, int _msgType, int _ep, int _srcPe, int _ml, CmiObjId *_idx) :
451     event(_event), msgType(_msgType), ep(_ep), srcPe(_srcPe), ml(_ml), idx(_idx) { }
452 };
453
454 /// class for recording trace projections events 
455 /**
456   TraceProjections will log Converse/Charm++ events and write into .log files;
457   events descriptions will be written into .sts file.
458 */
459 class TraceProjections : public Trace {
460 #ifdef PROJ_ANALYSIS
461   // The macro is here "just-in-case". Somehow, it seems it is not necessary
462   //   to declare friend classes ahead of time in C++.
463   friend class TraceProjectionsBOC;
464   friend class KMeansBOC;
465 #endif // PROJ_ANALYSIS
466  private:
467     LogPool* _logPool;        /**<  logpool for all events */
468     int curevent;
469     int execEvent;
470     int execEp;
471     int execPe;
472     int inEntry;
473     int computationStarted;
474
475     int funcCount;
476     CkHashtableT<StrKey,int> funcHashtable;
477
478     int traceNestedEvents;
479     CkQ<NestedEvent> nestedEvents;
480     
481     int currentPhaseID;
482     LogEntry* lastPhaseEvent;
483
484     //as user now can specify the idx, it's possible that user may specify an existing idx
485     //so that we need a data structure to track idx. --added by Chao Mei
486     CkVec<int> idxVec;
487     int idxRegistered(int idx);    
488 #if CMK_HAS_COUNTER_PAPI
489     int papiEventSet;
490     LONG_LONG_PAPI papiValues[NUMPAPIEVENTS];
491 #endif
492 public:
493     int converseExit; // used for exits that bypass CkExit.
494     double endTime;
495
496     TraceProjections(char **argv);
497     void userEvent(int e);
498     void userBracketEvent(int e, double bt, double et);
499     void userSuppliedBracketedNote(char*, int, double, double);
500
501     void userSuppliedData(int e);
502     void userSuppliedNote(char* note);
503     void memoryUsage(double m);
504     void creation(envelope *e, int epIdx, int num=1);
505     void creation(char *m);
506     void creationMulticast(envelope *e, int epIdx, int num=1, int *pelist=NULL);
507     void creationDone(int num=1);
508     void beginExecute(envelope *e);
509     void beginExecute(char *msg);
510     void beginExecute(CmiObjId  *tid);
511     void beginExecute(int event,int msgType,int ep,int srcPe,int ml,CmiObjId *idx=NULL);
512     void changeLastEntryTimestamp(double ts);
513     void beginExecuteLocal(int event,int msgType,int ep,int srcPe,int ml,CmiObjId *idx=NULL);
514     void endExecute(void);
515     void endExecute(char *msg);
516     void endExecuteLocal(void);
517     void messageRecv(char *env, int pe);
518     void beginIdle(double curWallTime);
519     void endIdle(double curWallTime);
520     void beginPack(void);
521     void endPack(void);
522     void beginUnpack(void);
523     void endUnpack(void);
524     void enqueue(envelope *e);
525     void dequeue(envelope *e);
526     void beginComputation(void);
527     void endComputation(void);
528
529     int traceRegisterUserEvent(const char*, int);
530     void traceClearEps();
531     void traceWriteSts();
532     void traceClose();
533     void traceBegin();
534     void traceEnd();
535 #if CMK_SMP_TRACE_COMMTHREAD
536     void traceBeginOnCommThread();
537     void traceEndOnCommThread();
538 #endif
539     void traceCommSetMsgID(char *msg);
540     void traceGetMsgID(char *msg, int *pe, int *event);
541     void traceSetMsgID(char *msg, int pe, int event);
542     void traceFlushLog() { _logPool->flushLogBuffer(); }
543
544     //functions that perform function tracing
545     CkHashtableIterator *getfuncIterator(){return funcHashtable.iterator();};
546     int getFuncNumber(){return funcHashtable.numObjects();};
547     void regFunc(const char *name, int &idx, int idxSpecifiedByUser=0);
548     void beginFunc(char *name,char *file,int line);
549     void beginFunc(int idx,char *file,int line);
550     void endFunc(char *name);
551     void endFunc(int num);
552
553     /* start recognizing phases in trace-projections */
554     /* _TRACE_END_PHASE must be called collectively on all processors */
555     /*   in order for phase numbers to match up. */
556     void endPhase();
557
558     /* This is for moving projections to being a charm++ module */
559     void closeTrace(void);
560
561     void setWriteData(bool b){
562       _logPool->setWriteData(b);
563     }
564
565     /* for overiding basic thread listener support in Trace class */
566     virtual void traceAddThreadListeners(CthThread tid, envelope *e);
567 };
568
569 using namespace PUP;
570
571 class toProjectionsFile : public toTextFile {
572  protected:
573   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
574  public:
575   //Begin writing to this file, which should be opened for ascii write.
576   toProjectionsFile(FILE *f_) :toTextFile(f_) {}
577 };
578 class fromProjectionsFile : public fromTextFile {
579  protected:
580   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
581  public:
582   //Begin writing to this file, which should be opened for ascii read.
583   fromProjectionsFile(FILE *f_) :fromTextFile(f_) {}
584 };
585
586 #if CMK_PROJECTIONS_USE_ZLIB
587 class toProjectionsGZFile : public PUP::er {
588   gzFile f;
589  protected:
590   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
591  public:
592   //Begin writing to this gz file, which should be opened for gz write.
593   toProjectionsGZFile(gzFile f_) :er(IS_PACKING), f(f_) {}
594 };
595 #endif
596
597
598
599
600 #if CMK_TRACE_ENABLED
601 /// Disable the outputting of the trace logs
602 void disableTraceLogOutput();
603
604 /// Enable the outputting of the trace logs
605 void enableTraceLogOutput();
606
607 /// Force the log file to be flushed
608 void flushTraceLog();
609 #else
610 static inline void disableTraceLogOutput() { }
611 static inline void enableTraceLogOutput() { }
612 static inline void flushTraceLog() { }
613 #endif
614
615 #endif
616
617 /*@}*/