15 #include "trace-common.h"
16 #include "ckhashtable.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) \
31 int result = fprintf(f,string,data); \
33 CmiAbort("Projections I/O error!"); \
37 /// a log entry in trace projection
41 double endTime
; // Should be used for all bracketed events. Currently only used for bracketed user supplied note
49 int nestedID
; // Nested thread ID, e.g. virtual AMPI rank number
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).
60 #if CMK_HAS_COUNTER_PAPI
61 LONG_LONG_PAPI papiValues
[NUMPAPIEVENTS
];
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;
87 userSuppliedNote
= NULL
;
95 LogEntry(double _time
,unsigned char _type
,unsigned short _funcID
,
96 int _lineNum
,char *_fileName
){
101 userSuppliedNote
= NULL
;
107 // Constructor for User Supplied Data
108 LogEntry(double _time
,unsigned char _type
, int value
,
109 int _lineNum
,char *_fileName
){
112 userSuppliedData
= value
;
113 userSuppliedNote
= NULL
;
119 // Constructor for User Supplied Data
120 LogEntry(double _time
,unsigned char _type
, char* note
,
121 int _lineNum
,char *_fileName
){
128 setUserSuppliedNote(note
);
132 // Constructor for bracketed user supplied note
133 LogEntry(double bt
, double et
, unsigned char _type
, char *note
, int eventID
){
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
;
157 if (d
) id
= *d
; else {id
.id
[0]=id
.id
[1]=id
.id
[2]=id
.id
[3]=-1; };
160 userSuppliedNote
= NULL
;
161 if (pelist
!= NULL
) {
162 pes
= new int[numPe
];
163 for (int i
=0; i
<numPe
; i
++) {
173 void setFName(char *_fileName
){
174 if(_fileName
== NULL
){
178 fName
= new char[strlen(_fileName
)+2];
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
);
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
) {
214 memUsage
= _memUsage
;
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 *) { }
229 void setNewStartTime(double t
) {
231 if (endTime
>=t
) endTime
-= t
;
232 if (recvTime
>=t
) recvTime
-= t
;
235 void pup(PUP::er
&p
);
237 if (fName
) delete [] fName
;
238 if (userSuppliedNote
) delete [] userSuppliedNote
;
242 class TraceProjections
;
244 /// log pool in trace projection
246 friend class TraceProjections
;
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
;
256 bool writeSummaryFiles
;
264 unsigned int poolSize
;
265 unsigned int numEntries
;
266 unsigned int lastCreationEvent
;
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
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
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
;
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;}
326 void setCompressed(int c
) { compressed
= c
; }
328 void createFile(const char *fix
="");
329 void createSts(const char *fix
="");
331 void openLog(const char *mode
);
334 void write(int writedelta
);
336 void writeSts(TraceProjections
*traceProj
);
339 void initializePhases() {
340 keepPhase
= new bool[numPhases
];
341 for (int i
=0; i
<numPhases
; i
++) {
346 void setAllPhases(bool val
) {
347 for (int i
=0; i
<numPhases
; i
++) {
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
){
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
400 StrKey(const char *name
){
402 str
= (char *)malloc((len
+1)*sizeof(char));
405 for(unsigned int i
=0;i
<len
;i
++){
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){
419 if(p
->len
!= q
->len
){
422 for(unsigned int i
=0;i
<p
->len
;i
++){
423 if(p
->str
[i
] != q
->str
[i
]){
429 inline CkHashCode
hash() const{
432 inline int compare(const StrKey
&t
) const {
436 for(unsigned int i
=0;i
<len
;i
++){
437 if(str
[i
] != t
.str
[i
]){
443 inline const char *getStr() const {
450 int event
, msgType
, ep
, srcPe
, ml
;
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
{
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
470 LogPool
* _logPool
; /**< logpool for all events */
476 bool computationStarted
;
477 bool traceNestedEvents
;
479 bool converseExit
; // used for exits that bypass CkExit.
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
492 int idxRegistered(int idx
);
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);
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();
542 #if CMK_SMP_TRACE_COMMTHREAD
543 void traceBeginOnCommThread();
544 void traceEndOnCommThread();
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. */
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
);
569 class toProjectionsFile
: public toTextFile
{
571 virtual void bytes(void *p
,size_t n
,size_t itemSize
,dataType t
);
573 //Begin writing to this file, which should be opened for ascii write.
574 toProjectionsFile(FILE *f_
) :toTextFile(f_
) {}
576 class fromProjectionsFile
: public fromTextFile
{
578 virtual void bytes(void *p
,size_t n
,size_t itemSize
,dataType t
);
580 //Begin writing to this file, which should be opened for ascii read.
581 fromProjectionsFile(FILE *f_
) :fromTextFile(f_
) {}
585 class toProjectionsGZFile
: public PUP::er
{
588 virtual void bytes(void *p
,size_t n
,size_t itemSize
,dataType t
);
590 //Begin writing to this gz file, which should be opened for gz write.
591 toProjectionsGZFile(gzFile f_
) :er(IS_PACKING
), f(f_
) {}
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();
606 static inline void disableTraceLogOutput() { }
607 static inline void enableTraceLogOutput() { }