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