Updated trace modules to generate papi traces and accept AMPI user function
authorChee Wai Lee <cheelee@illinois.edu>
Tue, 30 Mar 2004 21:24:07 +0000 (21:24 +0000)
committerChee Wai Lee <cheelee@illinois.edu>
Tue, 30 Mar 2004 21:24:07 +0000 (21:24 +0000)
tracing. The new version of projections is now 6.6

src/ck-perf/trace-common.C
src/ck-perf/trace-projections.C
src/ck-perf/trace-projections.h
src/ck-perf/trace.h

index 1cc9abd7b9c2a7f941812b8617fffc47329d2b0d..a0f73b79146e7b766ecd3945e8519b4356f141a5 100644 (file)
@@ -137,6 +137,10 @@ extern void traceWriteSTS(FILE *stsfp,int nUserEvents) {
   fprintf(stsfp, "TOTAL_MSGS %d\n", _msgTable.size());
   fprintf(stsfp, "TOTAL_PSEUDOS %d\n", 0);
   fprintf(stsfp, "TOTAL_EVENTS %d\n", nUserEvents);
+#if CMK_HAS_COUNTER_PAPI
+  // **CW** for now, hardcode ... 
+  fprintf(stsfp, "TOTAL_PAPI_EVENTS %d\n", 2);
+#endif
   int i;
   for(i=0;i<_chareTable.size();i++)
     fprintf(stsfp, "CHARE %d %s\n", i, _chareTable[i]->name);
@@ -145,6 +149,11 @@ extern void traceWriteSTS(FILE *stsfp,int nUserEvents) {
                  _entryTable[i]->chareIdx, _entryTable[i]->msgIdx);
   for(i=0;i<_msgTable.size();i++)
     fprintf(stsfp, "MESSAGE %d %d\n", i, _msgTable[i]->size);
+#if CMK_HAS_COUNTER_PAPI
+  // **CW** for now, hardcode ... 
+  fprintf(stsfp, "PAPI_EVENT %d %s\n", 0, "PAPI_TOT_INS");
+  fprintf(stsfp, "PAPI_EVENT %d %s\n", 1, "PAPI_L1_DCM");
+#endif
 }
 
 
index 675a242d193163c23b6360de9baca38f8a570b8a..2c89e840dcb4f85b1df7cf51eb2730cd1d273403 100644 (file)
@@ -60,6 +60,16 @@ On T3E, we need to have file number control by open/close files only when needed
   #define CLOSE_LOG
 #endif
 
+#if CMK_HAS_COUNTER_PAPI
+// these variables should be Ckpvs (I think) since the trace module is created
+// for each processor (group).
+//
+// For now, we trace only two events - # Floating Point Instructions &
+// # L1 Cache Misses.
+int numPAPIEvents = 2;
+int papiEventSet = PAPI_NULL;
+int papiEvents[] = {PAPI_TOT_INS, PAPI_L1_DCM};
+#endif
 
 void LogPool::openLog(const char *mode)
 {
@@ -131,6 +141,10 @@ void LogPool::closeLog(void)
 */
 void _createTraceprojections(char **argv)
 {
+#if CMK_HAS_COUNTER_PAPI
+  int papiRetValue = 0;
+#endif
+
   DEBUGF(("%d createTraceProjections\n", CkMyPe()));
   CkpvInitialize(CkVec<char *>, usrEventlist);
   CkpvInitialize(CkVec<UsrEvent *>*, usrEvents);
@@ -142,6 +156,22 @@ void _createTraceprojections(char **argv)
   CkpvInitialize(Trace*, _trace);
   CkpvAccess(_trace) = new  TraceProjections(argv);
   CkpvAccess(_traces)->addTrace(CkpvAccess(_trace));
+
+#if CMK_HAS_COUNTER_PAPI
+  // We initialize and create the event sets for use with PAPI here.
+  papiRetValue = PAPI_library_init(PAPI_VER_CURRENT);
+  if (papiRetValue != PAPI_VER_CURRENT) {
+    CmiAbort("PAPI Library initialization failure!\n");
+  }
+  if (PAPI_create_eventset(&papiEventSet) != PAPI_OK) {
+    CmiAbort("PAPI failed to create event set!\n");
+  }
+  if (PAPI_add_events(papiEventSet, papiEvents, numPAPIEvents) != PAPI_OK) {
+    CmiAbort("PAPI failed to add designated events!\n");
+  }
+  CkpvAccess(_trace)->papiValues = new long_long[numPAPIEvents];
+  memset(CkpvAccess(_trace)->papiValues, 0, numPAPIEvents*sizeof(long_long));
+#endif
 }
 
 LogPool::LogPool(char *pgm) {
@@ -344,7 +374,7 @@ void LogPool::writeSts(void)
   traceWriteSTS(stsfp,CkpvAccess(usrEvents)->length());
   for(int i=0;i<CkpvAccess(usrEvents)->length();i++){
     fprintf(stsfp, "EVENT %d %s\n", (*CkpvAccess(usrEvents))[i]->e, (*CkpvAccess(usrEvents))[i]->str);
-       }       
+  }    
   fprintf(stsfp, "END\n");
   fclose(stsfp);
 }
@@ -362,10 +392,12 @@ static void updateProjLog(void *data, double t, double recvT, void *ptr)
 }
 #endif
 
-void LogPool::add(UChar type,UShort mIdx,UShort eIdx,double time,int event,int pe, int ml, CmiObjId *id, double recvT, double cpuT) 
+void LogPool::add(UChar type,UShort mIdx,UShort eIdx,double time,int event,int pe, int ml, CmiObjId *id, double recvT, double cpuT, int numPap, 
+                 LONG_LONG_PAPI *papVals) 
 {
   new (&pool[numEntries++])
-    LogEntry(time, type, mIdx, eIdx, event, pe, ml, id, recvT, cpuT);
+    LogEntry(time, type, mIdx, eIdx, event, pe, ml, id, recvT, cpuT, numPap,
+            papVals);
   if(poolSize==numEntries) {
     double writeTime = TraceTimer();
     writeLog();
@@ -456,6 +488,25 @@ LogEntry::LogEntry(double tm, unsigned short m, unsigned short e, int ev, int p,
     }
 }
 
+LogEntry::LogEntry(double tm, unsigned char t, unsigned short m, 
+                  unsigned short e, int ev,
+                  int p, int ml, CmiObjId *d, double rt,
+                  double cpuT, int numPapiEvts, LONG_LONG_PAPI *papiVals)
+{
+  type = t; mIdx = m; eIdx = e; event = ev; pe = p; time = tm; msglen = ml;
+  if (d) id = *d; else {id.id[0]=id.id[1]=id.id[2]=0;};
+  recvTime = rt;
+  numPapiEvents = numPapiEvts; cputime = cpuT;
+  if (papiVals != NULL) {
+    papiValues = new LONG_LONG_PAPI[numPapiEvents];
+    for (int i=0; i<numPapiEvents; i++) {
+      papiValues[i] = papiVals[i];
+    }
+  } else {
+    papiValues = NULL;
+  }
+}
+
 void LogEntry::pup(PUP::er &p)
 {
   int itime, irecvtime, icputime;
@@ -484,6 +535,12 @@ void LogEntry::pup(PUP::er &p)
       p|mIdx; p|eIdx; p|itime; p|event; p|pe; 
       p|msglen; p|irecvtime; p|id.id[0]; p|id.id[1]; p|id.id[2];
       p|icputime;
+      p|numPapiEvents;
+      for (int i=0; i<numPapiEvents; i++) {
+       p|papiValues[i];
+      }
+      // **CW** I believe we still need to properly implement unpacking
+      // for papiValues ...
       if (p.isUnpacking()) {
        recvTime = irecvtime/1.0e6;
        cputime = icputime/1.0e6;
@@ -492,6 +549,10 @@ void LogEntry::pup(PUP::er &p)
     case END_PROCESSING:
       if (p.isPacking()) icputime = (int)(1.0e6*cputime);
       p|mIdx; p|eIdx; p|itime; p|event; p|pe; p|msglen; p|icputime;
+      p|numPapiEvents;
+      for (int i=0; i<numPapiEvents; i++) {
+       p|papiValues[i];
+      }
       if (p.isUnpacking()) cputime = icputime/1.0e6;
       break;
     case CREATION:
@@ -511,6 +572,8 @@ void LogEntry::pup(PUP::er &p)
       else {
        for (int i=0; i<numpes; i++) p|pes[i];
       }
+      // **CW** I believe we still need to properly implement unpacking
+      // for pes ...
       if (p.isUnpacking()) recvTime = irecvtime/1.0e6;
       break;
     case MESSAGE_RECV:
@@ -727,22 +790,44 @@ void TraceProjections::creationDone(int num)
 
 void TraceProjections::beginExecute(CmiObjId *tid)
 {
+#if CMK_HAS_COUNTER_PAPI
+  if (PAPI_read(papiEventSet, CkpvAccess(_trace)->papiValues) != PAPI_OK) {
+    CmiAbort("PAPI failed to read at begin execute!\n");
+  }
+#endif
   if (checknested && inEntry) CmiAbort("Nested Begin Execute!\n");
   execEvent = CtvAccess(curThreadEvent);
   execEp = (-1);
+#if CMK_HAS_COUNTER_PAPI
+  _logPool->add(BEGIN_PROCESSING,ForChareMsg,_threadEP,TraceTimer(),
+               execEvent,CkMyPe(), 0, tid, 0.0, TraceCpuTimer(),
+               numPAPIEvents, CkpvAccess(_trace)->papiValues);
+#else
   _logPool->add(BEGIN_PROCESSING,ForChareMsg,_threadEP,TraceTimer(),
                              execEvent,CkMyPe(), 0, tid);
+#endif
   inEntry = 1;
 }
 
 void TraceProjections::beginExecute(envelope *e)
 {
   if(e==0) {
+#if CMK_HAS_COUNTER_PAPI
+    if (PAPI_read(papiEventSet, CkpvAccess(_trace)->papiValues) != PAPI_OK) {
+      CmiAbort("PAPI failed to read at begin execute!\n");
+    }
+#endif
     if (checknested && inEntry) CmiAbort("Nested Begin Execute!\n");
     execEvent = CtvAccess(curThreadEvent);
     execEp = (-1);
+#if CMK_HAS_COUNTER_PAPI
+    _logPool->add(BEGIN_PROCESSING,ForChareMsg,_threadEP,TraceTimer(),
+                 execEvent,CkMyPe(), 0, 0, 0.0, TraceCpuTimer(),
+                 numPAPIEvents, CkpvAccess(_trace)->papiValues);
+#else
     _logPool->add(BEGIN_PROCESSING,ForChareMsg,_threadEP,TraceTimer(),
-                             execEvent,CkMyPe(), 0, 0, 0.0, TraceCpuTimer());
+                 execEvent,CkMyPe(), 0, 0, 0.0, TraceCpuTimer());
+#endif
     inEntry = 1;
   } else {
     beginExecute(e->getEvent(),e->getMsgtype(),e->getEpIdx(),e->getSrcPe(),e->getTotalsize());
@@ -751,19 +836,46 @@ void TraceProjections::beginExecute(envelope *e)
 
 void TraceProjections::beginExecute(int event,int msgType,int ep,int srcPe, int mlen,CmiObjId *idx)
 {
+#if CMK_HAS_COUNTER_PAPI
+  if (PAPI_read(papiEventSet, CkpvAccess(_trace)->papiValues) != PAPI_OK) {
+    CmiAbort("PAPI failed to read at begin execute!\n");
+  }
+#endif
   if (checknested && inEntry) CmiAbort("Nested Begin Execute!\n");
   execEvent=event;
   execEp=ep;
   execPe=srcPe;
+#if CMK_HAS_COUNTER_PAPI
   _logPool->add(BEGIN_PROCESSING,msgType,ep,TraceTimer(),event,
-                             srcPe, mlen, idx, 0.0, TraceCpuTimer());
+               srcPe, mlen, idx, 0.0, TraceCpuTimer(),
+               numPAPIEvents, CkpvAccess(_trace)->papiValues);
+#else
+  _logPool->add(BEGIN_PROCESSING,msgType,ep,TraceTimer(),event,
+               srcPe, mlen, idx, 0.0, TraceCpuTimer());
+#endif
   inEntry = 1;
 }
 
 void TraceProjections::endExecute(void)
 {
+#if CMK_HAS_COUNTER_PAPI
+  if (PAPI_read(papiEventSet, CkpvAccess(_trace)->papiValues) != PAPI_OK) {
+    CmiAbort("PAPI failed to read at end execute!\n");
+  }
+#endif
   if (checknested && !inEntry) CmiAbort("Nested EndExecute!\n");
   double cputime = TraceCpuTimer();
+#if CMK_HAS_COUNTER_PAPI
+  if(execEp == (-1)) {
+    _logPool->add(END_PROCESSING,0,_threadEP,TraceTimer(),
+                 execEvent,CkMyPe(),0,0,0.0,cputime,
+                 numPAPIEvents, CkpvAccess(_trace)->papiValues);
+  } else {
+    _logPool->add(END_PROCESSING,0,execEp,TraceTimer(),
+                 execEvent,execPe,0,0,0.0,cputime,
+                 numPAPIEvents, CkpvAccess(_trace)->papiValues);
+  }
+#else
   if(execEp == (-1)) {
     _logPool->add(END_PROCESSING,0,_threadEP,TraceTimer(),
                              execEvent,CkMyPe(),0,0,0.0,cputime);
@@ -771,6 +883,7 @@ void TraceProjections::endExecute(void)
     _logPool->add(END_PROCESSING,0,execEp,TraceTimer(),
                              execEvent,execPe,0,0,0.0,cputime);
   }
+#endif
   inEntry = 0;
 }
 
@@ -834,10 +947,24 @@ void TraceProjections::beginComputation(void)
 //  CkpvAccess(traceInitTime) = TRACE_TIMER();
 //  CkpvAccess(traceInitCpuTime) = TRACE_CPUTIMER();
   _logPool->add(BEGIN_COMPUTATION, 0, 0, TraceTimer(), -1, -1);
+#if CMK_HAS_COUNTER_PAPI
+  // we start the counters here
+  if (PAPI_start(papiEventSet) != PAPI_OK) {
+    CmiAbort("PAPI failed to start designated counters!\n");
+  }
+#endif
 }
 
 void TraceProjections::endComputation(void)
 {
+#if CMK_HAS_COUNTER_PAPI
+  // we stop the counters here. A silent failure is alright since we
+  // are already at the end of the program.
+  if (PAPI_stop(papiEventSet,
+               CkpvAccess(_trace)->papiValues) != PAPI_OK) {
+    CkPrintf("Warning: PAPI failed to stop correctly!\n");
+  }
+#endif
   _logPool->add(END_COMPUTATION, 0, 0, TraceTimer(), -1, -1);
 }
 
@@ -891,6 +1018,7 @@ void toProjectionsFile::bytes(void *p,int n,size_t itemSize,dataType t)
     case Tulong: CheckAndFPrintF(f," %lu",((unsigned long *)p)[i]); break;
     case Tfloat: CheckAndFPrintF(f," %.7g",((float *)p)[i]); break;
     case Tdouble: CheckAndFPrintF(f," %.15g",((double *)p)[i]); break;
+    case Tlonglong: CheckAndFPrintF(f," %lld",((long long *)p)[i]); break;
     default: CmiAbort("Unrecognized pup type code!");
     };
 }
index 129b0cb4897b2c2b3ae862334ab94d0e52c1294c..8490a16d256eb70f4fd81cc3c8ab7a5b52009d18 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "pup.h"
 
-#define PROJECTION_VERSION  "6.5"
+#define PROJECTION_VERSION  "6.6"
 
 // Macro to make projections check for errors before an fprintf succeeds.
 #define CheckAndFPrintF(f,string,data) \
@@ -49,6 +49,8 @@ class LogEntry {
     CmiObjId   id;
     int numpes;
     int *pes;
+    int numPapiEvents;
+    LONG_LONG_PAPI *papiValues;
     unsigned char type; 
                char *fName;
                int flen;
@@ -77,6 +79,12 @@ class LogEntry {
     // **CW** new constructor for multicast data
     LogEntry(double tm, unsigned short m, unsigned short e, int ev, int p,
             int ml, CmiObjId *d, double rt, int num, int *pelist);
+    // **CW** this prototype is used for PAPI events (which has a dynamic
+    // structure to copy).
+    LogEntry(double tm, unsigned char t, unsigned short m, unsigned short e, 
+            int ev, int p,
+            int ml, CmiObjId *d, double rt, double cpuT, int numPap, 
+            LONG_LONG_PAPI *papVals);
     void *operator new(size_t s) {void*ret=malloc(s);_MEMCHECK(ret);return ret;}
     void *operator new(size_t, void *ptr) { return ptr; }
     void operator delete(void *ptr) {free(ptr); }
@@ -130,8 +138,8 @@ class LogPool {
     void writeLog(void);
     void write(int writedelta);
     void writeSts(void);
-    void add(unsigned char type,unsigned short mIdx,unsigned short eIdx,double time,int event,int pe, int ml=0, CmiObjId* id=0, double recvT=0., double cpuT=0.0);
-               void add(unsigned char type,double time,unsigned short funcID,int lineNum,char *fileName);
+    void add(unsigned char type,unsigned short mIdx,unsigned short eIdx,double time,int event,int pe, int ml=0, CmiObjId* id=0, double recvT=0., double cpuT=0.0, int numPap=0, LONG_LONG_PAPI *papVals=NULL);
+    void add(unsigned char type,double time,unsigned short funcID,int lineNum,char *fileName);
     void addCreationMulticast(unsigned short mIdx,unsigned short eIdx,double time,int event,int pe, int ml=0, CmiObjId* id=0, double recvT=0., int num=0, int *pelist=NULL);
     void postProcessLog();
 };
index 9adabab3db6bff139bcc1135bab42de50f0066a3..9f47675f185677019aa0f446a45a97526e6e571e 100644 (file)
@@ -31,10 +31,21 @@ CkpvExtern(int, traceOnPe);
 #  define TRACE_CHARM_PE()  (CkMyRank() != CkMyNodeSize())
 #endif
 
+// A hack. We need to somehow tell the pup framework what size
+// long_long is wrt PAPI.
+#if CMK_HAS_COUNTER_PAPI
+typedef long_long LONG_LONG_PAPI;
+#else
+typedef int LONG_LONG_PAPI;
+#endif
+
 // Base class of all tracing strategies.
 // 
 class Trace {
   public:
+
+    LONG_LONG_PAPI *papiValues;
+
     virtual int traceOnPE() { return TRACE_CHARM_PE(); }
     // turn trace on/off, note that charm will automatically call traceBegin()
     // at the beginning of every run unless the command line option "+traceoff"
@@ -54,6 +65,15 @@ class Trace {
     virtual void creationDone(int num=1) {}
     // ???
     virtual void messageRecv(char *env, int pe) {}
+    virtual void beginSDAGBlock(
+      int event,   // event type defined in trace-common.h
+      int msgType, // message type
+      int ep,      // Charm++ entry point (will correspond to sts file) 
+      int srcPe,   // Which PE originated the call
+      int ml,      // message size
+      CmiObjId* idx)    // index
+    { }
+    virtual void endSDAGBlock(void) {}
     // **************************************************************
     // begin/end execution of a Charm++ entry point
     // NOTE: begin/endPack and begin/endUnpack can be called in between
@@ -137,6 +157,8 @@ public:
     void creationMulticast(envelope *env, int ep, int num=1, int *pelist=NULL);
     
     inline void creationDone(int num=1) { ALLDO(creationDone(num)); }
+    inline void beginSDAGBlock(int event,int msgType,int ep,int srcPe, int mlen,CmiObjId *idx=NULL) {ALLDO(beginSDAGBlock(event, msgType, ep, srcPe, mlen,idx));}
+    inline void endSDAGBlock(void) {ALLREVERSEDO(endExecute());}
     inline void beginExecute(envelope *env) {ALLDO(beginExecute(env));}
     inline void beginExecute(CmiObjId *tid) {ALLDO(beginExecute(tid));}
     inline void beginExecute(int event,int msgType,int ep,int srcPe, int mlen,CmiObjId *idx=NULL) {ALLDO(beginExecute(event, msgType, ep, srcPe, mlen,idx));}
@@ -202,6 +224,8 @@ extern "C" {
 #define _TRACE_CREATION_N(env, num) _TRACE_ONLY(CkpvAccess(_traces)->creation(env,env->getEpIdx(), num))
 #define _TRACE_CREATION_MULTICAST(env, num, pelist) _TRACE_ONLY(CkpvAccess(_traces)->creationMulticast(env, env->getEpIdx(), num, pelist))
 #define _TRACE_CREATION_DONE(num) _TRACE_ONLY(CkpvAccess(_traces)->creationDone(num))
+#define _TRACE_BEGIN_SDAG(env) _TRACE_ONLY(CkpvAccess(_traces)->beginSDAGBlock(env))
+#define _TRACE_END_SDAG(env) _TRACE_ONLY(CkpvAccess(_traces)->endSDAGBlock(env))
 #define _TRACE_BEGIN_EXECUTE(env) _TRACE_ONLY(CkpvAccess(_traces)->beginExecute(env))
 #define _TRACE_BEGIN_EXECUTE_DETAILED(evt,typ,ep,src,mlen,idx) \
        _TRACE_ONLY(CkpvAccess(_traces)->beginExecute(evt,typ,ep,src,mlen,idx))