ck-perf/trace-projections.C

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * $Source: /cvsroot/charm/src/ck-perf/trace-projections.C,v $
00003  * $Author: idooley2 $
00004  * $Date: 2008-02-04 22:20:48 $
00005  * $Revision: 2.126 $
00006  *****************************************************************************/
00007 
00008 
00013 
00014 #include <string.h>
00015 
00016 #include "charm++.h"
00017 #include "trace-projections.h"
00018 #include "trace-projectionsBOC.h"
00019 
00020 #define DEBUGF(x)           // CmiPrintf x
00021 
00022 #define DefaultLogBufSize      1000000
00023 
00024 // **CW** Simple delta encoding implementation
00025 // delta encoding is on by default. It may be turned off later in
00026 // the runtime.
00027 int deltaLog;
00028 int nonDeltaLog;
00029 
00030 int checknested=0;              // check illegal nested begin/end execute 
00031 
00032 CkGroupID traceProjectionsGID;
00033 
00034 CkpvStaticDeclare(TraceProjections*, _trace);
00035 CtvStaticDeclare(int,curThreadEvent);
00036 
00037 CkpvDeclare(bool, useOutlierAnalysis);
00038 CkpvDeclare(int, CtrLogBufSize);
00039 
00040 typedef CkVec<char *>  usrEventVec;
00041 CkpvStaticDeclare(usrEventVec, usrEventlist);
00042 class UsrEvent {
00043 public:
00044   int e;
00045   char *str;
00046   UsrEvent(int _e, char* _s): e(_e),str(_s) {}
00047 };
00048 CkpvStaticDeclare(CkVec<UsrEvent *>*, usrEvents);
00049 
00050 #ifdef CMK_OPTIMIZE
00051 static int warned=0;
00052 #define OPTIMIZED_VERSION       \
00053         if (!warned) { warned=1;        \
00054         CmiPrintf("\n\n!!!! Warning: traceUserEvent not available in optimized version!!!!\n\n\n"); }
00055 #else
00056 #define OPTIMIZED_VERSION /*empty*/
00057 #endif
00058 
00059 /*
00060 On T3E, we need to have file number control by open/close files only when needed.
00061 */
00062 #if CMK_TRACE_LOGFILE_NUM_CONTROL
00063   #define OPEN_LOG openLog("a");
00064   #define CLOSE_LOG closeLog();
00065 #else
00066   #define OPEN_LOG
00067   #define CLOSE_LOG
00068 #endif
00069 
00070 #if CMK_HAS_COUNTER_PAPI
00071 int numPAPIEvents = 2;
00072 int papiEvents[] = { PAPI_L3_DCM, PAPI_FP_OPS };
00073 char *papiEventNames[] = {"PAPI_L3_DCM", "PAPI_FP_OPS"};
00074 #endif
00075 
00080 void _createTraceprojections(char **argv)
00081 {
00082   DEBUGF(("%d createTraceProjections\n", CkMyPe()));
00083   CkpvInitialize(CkVec<char *>, usrEventlist);
00084   CkpvInitialize(CkVec<UsrEvent *>*, usrEvents);
00085   CkpvAccess(usrEvents) = new CkVec<UsrEvent *>();
00086 #if CMK_BLUEGENE_CHARM
00087   // CthRegister does not call the constructor
00088 //  CkpvAccess(usrEvents) = CkVec<UsrEvent *>();
00089 #endif
00090   CkpvInitialize(TraceProjections*, _trace);
00091   CkpvAccess(_trace) = new  TraceProjections(argv);
00092   CkpvAccess(_traces)->addTrace(CkpvAccess(_trace));
00093 }
00094  
00095 /* ****** CW TEMPORARY LOCATION ***** Support for thread listeners */
00096 
00097 struct TraceThreadListener {
00098   struct CthThreadListener base;
00099   int event;
00100   int msgType;
00101   int ep;
00102   int srcPe;
00103   int ml;
00104   CmiObjId idx;
00105 };
00106 
00107 
00108 extern "C"
00109 void traceThreadListener_suspend(struct CthThreadListener *l)
00110 {
00111   TraceThreadListener *a=(TraceThreadListener *)l;
00112   /* here, we activate the appropriate trace codes for the appropriate
00113      registered modules */
00114   traceSuspend();
00115 }
00116 
00117 extern "C"
00118 void traceThreadListener_resume(struct CthThreadListener *l) 
00119 {
00120   TraceThreadListener *a=(TraceThreadListener *)l;
00121   /* here, we activate the appropriate trace codes for the appropriate
00122      registered modules */
00123   _TRACE_BEGIN_EXECUTE_DETAILED(a->event,a->msgType,a->ep,a->srcPe,a->ml,
00124                                 CthGetThreadID(a->base.thread));
00125   a->event=-1;
00126   a->srcPe=CkMyPe(); /* potential lie to migrated threads */
00127   a->ml=0;
00128 }
00129 
00130 extern "C"
00131 void traceThreadListener_free(struct CthThreadListener *l) 
00132 {
00133   TraceThreadListener *a=(TraceThreadListener *)l;
00134   delete a;
00135 }
00136 
00137 void TraceProjections::traceAddThreadListeners(CthThread tid, envelope *e)
00138 {
00139 #ifndef CMK_OPTIMIZE
00140   /* strip essential information from the envelope */
00141   TraceThreadListener *a= new TraceThreadListener;
00142   
00143   a->base.suspend=traceThreadListener_suspend;
00144   a->base.resume=traceThreadListener_resume;
00145   a->base.free=traceThreadListener_free;
00146   a->event=e->getEvent();
00147   a->msgType=e->getMsgtype();
00148   a->ep=e->getEpIdx();
00149   a->srcPe=e->getSrcPe();
00150   a->ml=e->getTotalsize();
00151 
00152   CthAddListener(tid, (CthThreadListener *)a);
00153 #endif
00154 }
00155 
00156 void LogPool::openLog(const char *mode)
00157 {
00158 #if CMK_PROJECTIONS_USE_ZLIB
00159   if(compressed) {
00160     if (nonDeltaLog) {
00161       do {
00162         zfp = gzopen(fname, mode);
00163       } while (!zfp && (errno == EINTR || errno == EMFILE));
00164       if(!zfp) CmiAbort("Cannot open Projections Compressed Non Delta Trace File for writing...\n");
00165     }
00166     if (deltaLog) {
00167       do {
00168         deltazfp = gzopen(dfname, mode);
00169       } while (!deltazfp && (errno == EINTR || errno == EMFILE));
00170       if (!deltazfp) 
00171         CmiAbort("Cannot open Projections Compressed Delta Trace File for writing...\n");
00172     }
00173   } else {
00174     if (nonDeltaLog) {
00175       do {
00176         fp = fopen(fname, mode);
00177       } while (!fp && (errno == EINTR || errno == EMFILE));
00178       if (!fp) {
00179         CkPrintf("[%d] Attempting to open file [%s]\n",CkMyPe(),fname);
00180         CmiAbort("Cannot open Projections Non Delta Trace File for writing...\n");
00181       }
00182     }
00183     if (deltaLog) {
00184       do {
00185         deltafp = fopen(dfname, mode);
00186       } while (!deltafp && (errno == EINTR || errno == EMFILE));
00187       if (!deltafp) 
00188         CmiAbort("Cannot open Projections Delta Trace File for writing...\n");
00189     }
00190   }
00191 #else
00192   if (nonDeltaLog) {
00193     do {
00194       fp = fopen(fname, mode);
00195     } while (!fp && (errno == EINTR || errno == EMFILE));
00196     if (!fp) {
00197       CkPrintf("[%d] Attempting to open file [%s]\n",CkMyPe(),fname);
00198       CmiAbort("Cannot open Projections Non Delta Trace File for writing...\n");
00199     }
00200   }
00201   if (deltaLog) {
00202     do {
00203       deltafp = fopen(dfname, mode);
00204     } while (!deltafp && (errno == EINTR || errno == EMFILE));
00205     if(!deltafp) 
00206       CmiAbort("Cannot open Projections Delta Trace File for writing...\n");
00207   }
00208 #endif
00209 }
00210 
00211 void LogPool::closeLog(void)
00212 {
00213 #if CMK_PROJECTIONS_USE_ZLIB
00214   if(compressed) {
00215     if (nonDeltaLog) gzclose(zfp);
00216     if (deltaLog) gzclose(deltazfp);
00217     return;
00218   }
00219 #endif
00220   if (nonDeltaLog) { 
00221 #if !defined(_WIN32) || defined(__CYGWIN__)
00222     fsync(fileno(fp)); 
00223 #endif
00224     fclose(fp); 
00225   }
00226   if (deltaLog)  { 
00227 #if !defined(_WIN32) || defined(__CYGWIN__)
00228     fsync(fileno(deltafp)); 
00229 #endif
00230     fclose(deltafp);  
00231   }
00232 }
00233 
00234 LogPool::LogPool(char *pgm) {
00235   pool = new LogEntry[CkpvAccess(CtrLogBufSize)];
00236   // defaults to writing data (no outlier changes)
00237   writeData = true;
00238   numEntries = 0;
00239   // **CW** for simple delta encoding
00240   prevTime = 0.0;
00241   timeErr = 0.0;
00242   globalEndTime = 0.0;
00243   headerWritten = 0;
00244   fileCreated = false;
00245   poolSize = CkpvAccess(CtrLogBufSize);
00246   pgmname = new char[strlen(pgm)+1];
00247   strcpy(pgmname, pgm);
00248 }
00249 
00250 void LogPool::createFile(char *fix)
00251 {
00252   if (fileCreated) {
00253     return;
00254   }
00255   char pestr[10];
00256   sprintf(pestr, "%d", CkMyPe());
00257 #if CMK_PROJECTIONS_USE_ZLIB
00258   int len;
00259   if(compressed)
00260     len = strlen(pgmname)+strlen(fix)+strlen(".logold")+strlen(pestr)+strlen(".gz")+3;
00261   else
00262     len = strlen(pgmname)+strlen(fix)+strlen(".logold")+strlen(pestr)+3;
00263 #else
00264   int len = strlen(pgmname)+strlen(fix)+strlen(".logold")+strlen(pestr)+3;
00265 #endif
00266   if (nonDeltaLog) {
00267     fname = new char[len];
00268   }
00269   if (deltaLog) {
00270     dfname = new char[len];
00271   }
00272 #if CMK_PROJECTIONS_USE_ZLIB
00273   if(compressed) {
00274     if (deltaLog && nonDeltaLog) {
00275       sprintf(fname, "%s%s.%s.logold.gz", pgmname, fix, pestr);
00276       sprintf(dfname, "%s%s.%s.log.gz", pgmname, fix, pestr);
00277     } else {
00278       if (nonDeltaLog) {
00279         sprintf(fname, "%s%s.%s.log.gz", pgmname, fix, pestr);
00280       } else {
00281         sprintf(dfname, "%s%s.%s.log.gz", pgmname, fix, pestr);
00282       }
00283     }
00284   } else {
00285     if (deltaLog && nonDeltaLog) {
00286       sprintf(fname, "%s%s.%s.logold", pgmname, fix, pestr);
00287       sprintf(dfname, "%s%s.%s.log", pgmname, fix, pestr);
00288     } else {
00289       if (nonDeltaLog) {
00290         sprintf(fname, "%s%s.%s.log", pgmname, fix, pestr);
00291       } else {
00292         sprintf(dfname, "%s%s.%s.log", pgmname, fix, pestr);
00293       }
00294     }
00295   }
00296 #else
00297   if (deltaLog && nonDeltaLog) {
00298     sprintf(fname, "%s%s.%s.logold", pgmname, fix, pestr);
00299     sprintf(dfname, "%s%s.%s.log", pgmname, fix, pestr);
00300   } else {
00301     if (nonDeltaLog) {
00302       sprintf(fname, "%s%s.%s.log", pgmname, fix, pestr);
00303     } else {
00304       sprintf(dfname, "%s%s.%s.log", pgmname, fix, pestr);
00305     }
00306   }
00307 #endif
00308   fileCreated = true;
00309   openLog("w+");
00310   CLOSE_LOG 
00311 }
00312 
00313 void LogPool::createSts(char *fix)
00314 {
00315   CkAssert(CkMyPe() == 0);
00316   // create the sts file
00317   char *fname = new char[strlen(CkpvAccess(traceRoot))+strlen(fix)+strlen(".sts")+2];
00318   sprintf(fname, "%s%s.sts", CkpvAccess(traceRoot), fix);
00319   do
00320     {
00321       stsfp = fopen(fname, "w");
00322     } while (!stsfp && (errno == EINTR || errno == EMFILE));
00323   if(stsfp==0)
00324     CmiAbort("Cannot open projections sts file for writing.\n");
00325   delete[] fname;
00326 }  
00327 
00328 void LogPool::createRC()
00329 {
00330   // create the projections rc file.
00331   fname = 
00332     new char[strlen(CkpvAccess(traceRoot))+strlen(".projrc")+1];
00333   sprintf(fname, "%s.projrc", CkpvAccess(traceRoot));
00334   do {
00335     rcfp = fopen(fname, "w");
00336   } while (!rcfp && (errno == EINTR || errno == EMFILE));
00337   if (rcfp==0) {
00338     CmiAbort("Cannot open projections configuration file for writing.\n");
00339   }
00340   delete[] fname;
00341 }
00342 
00343 LogPool::~LogPool() 
00344 {
00345   if (writeData) {
00346     writeLog();
00347 #if !CMK_TRACE_LOGFILE_NUM_CONTROL
00348     closeLog();
00349 #endif
00350   }
00351 
00352 #if CMK_BLUEGENE_CHARM
00353   extern int correctTimeLog;
00354   if (correctTimeLog) {
00355     createFile("-bg");
00356     if (CkMyPe() == 0) {
00357       createSts("-bg");
00358     }
00359     writeHeader();
00360     if (CkMyPe() == 0) writeSts(NULL);
00361     postProcessLog();
00362   }
00363 #endif
00364 
00365   delete[] pool;
00366   delete [] fname;
00367 }
00368 
00369 void LogPool::writeHeader()
00370 {
00371   if (headerWritten) return;
00372   headerWritten = 1;
00373   if(!binary) {
00374 #if CMK_PROJECTIONS_USE_ZLIB
00375     if(compressed) {
00376       if (nonDeltaLog) {
00377         gzprintf(zfp, "PROJECTIONS-RECORD %d\n", numEntries);
00378       }
00379       if (deltaLog) {
00380         gzprintf(deltazfp, "PROJECTIONS-RECORD %d DELTA\n", numEntries);
00381       }
00382     } 
00383     else /* else clause is below... */
00384 #endif
00385     /*... may hang over from else above */ {
00386       if (nonDeltaLog) {
00387         fprintf(fp, "PROJECTIONS-RECORD %d\n", numEntries);
00388       }
00389       if (deltaLog) {
00390         fprintf(deltafp, "PROJECTIONS-RECORD %d DELTA\n", numEntries);
00391       }
00392     }
00393   }
00394   else { // binary
00395       if (nonDeltaLog) {
00396         fwrite(&numEntries,sizeof(numEntries),1,fp);
00397       }
00398       if (deltaLog) {
00399         fwrite(&numEntries,sizeof(numEntries),1,deltafp);
00400       }
00401   }
00402 }
00403 
00404 void LogPool::writeLog(void)
00405 {
00406   createFile();
00407   OPEN_LOG
00408   writeHeader();
00409   if (nonDeltaLog) write(0);
00410   if (deltaLog) write(1);
00411   CLOSE_LOG
00412 }
00413 
00414 void LogPool::write(int writedelta) 
00415 {
00416   // **CW** Simple delta encoding implementation
00417   // prevTime has to be maintained as an object variable because
00418   // LogPool::write may be called several times depending on the
00419   // +logsize value.
00420   PUP::er *p = NULL;
00421   if (binary) {
00422     p = new PUP::toDisk(writedelta?deltafp:fp);
00423   }
00424 #if CMK_PROJECTIONS_USE_ZLIB
00425   else if (compressed) {
00426     p = new toProjectionsGZFile(writedelta?deltazfp:zfp);
00427   }
00428 #endif
00429   else {
00430     p = new toProjectionsFile(writedelta?deltafp:fp);
00431   }
00432   CmiAssert(p);
00433   for(UInt i=0; i<numEntries; i++) {
00434     if (!writedelta) {
00435       pool[i].pup(*p);
00436     }
00437     else {      // delta
00438       double time = pool[i].time;
00439       if (pool[i].type != BEGIN_COMPUTATION && pool[i].type != END_COMPUTATION)
00440       {
00441         double timeDiff = (time-prevTime)*1.0e6;
00442         UInt intTimeDiff = (UInt)timeDiff;
00443         timeErr += timeDiff - intTimeDiff; /* timeErr is never >= 2.0 */
00444         if (timeErr > 1.0) {
00445           timeErr -= 1.0;
00446           intTimeDiff++;
00447         }
00448         pool[i].time = intTimeDiff/1.0e6;
00449       }
00450       pool[i].pup(*p);
00451       pool[i].time = time;      // restore time value
00452       prevTime = time;
00453     }
00454   }
00455   delete p;
00456 }
00457 
00458 void LogPool::writeSts(void)
00459 {
00460   // for whining compilers
00461   int i;
00462   char name[30];
00463   // generate an automatic unique ID for each log
00464   fprintf(stsfp, "PROJECTIONS_ID %s\n", "");
00465   fprintf(stsfp, "VERSION %s\n", PROJECTION_VERSION);
00466 #if CMK_HAS_COUNTER_PAPI
00467   fprintf(stsfp, "TOTAL_PAPI_EVENTS %d\n", numPAPIEvents);
00468   // for now, use i, next time use papiEvents[i].
00469   // **CW** papi event names is a hack.
00470   for (i=0;i<numPAPIEvents;i++) {
00471     fprintf(stsfp, "PAPI_EVENT %d %s\n", i, papiEventNames[i]);
00472   }
00473 #endif
00474   traceWriteSTS(stsfp,CkpvAccess(usrEvents)->length());
00475   for(i=0;i<CkpvAccess(usrEvents)->length();i++){
00476     fprintf(stsfp, "EVENT %d %s\n", (*CkpvAccess(usrEvents))[i]->e, (*CkpvAccess(usrEvents))[i]->str);
00477   }     
00478 }
00479 
00480 void LogPool::writeSts(TraceProjections *traceProj){
00481   writeSts();
00482   if (traceProj != NULL) {
00483     CkHashtableIterator  *funcIter = traceProj->getfuncIterator();
00484     funcIter->seekStart();
00485     int numFuncs = traceProj->getFuncNumber();
00486     fprintf(stsfp,"TOTAL_FUNCTIONS %d \n",numFuncs);
00487     while(funcIter->hasNext()) {
00488       StrKey *key;
00489       int *obj = (int *)funcIter->next((void **)&key);
00490       fprintf(stsfp,"FUNCTION %d %s \n",*obj,key->getStr());
00491     }
00492   }
00493   fprintf(stsfp, "END\n");
00494   fclose(stsfp);
00495 }
00496 
00497 void LogPool::writeRC(void)
00498 {
00499   CkAssert(CkMyPe() == 0);
00500   fprintf(rcfp,"RC_GLOBAL_END_TIME %lld\n",
00501           (CMK_TYPEDEF_UINT8)(1.0e6*globalEndTime));
00502   if (CkpvAccess(useOutlierAnalysis)) {
00503     fprintf(rcfp,"RC_OUTLIER_FILTERED true\n");
00504   } else {
00505     fprintf(rcfp,"RC_OUTLIER_FILTERED false\n");
00506   }       
00507   fclose(rcfp);
00508 }
00509 
00510 
00511 #if CMK_BLUEGENE_CHARM
00512 static void updateProjLog(void *data, double t, double recvT, void *ptr)
00513 {
00514   LogEntry *log = (LogEntry *)data;
00515   FILE *fp = *(FILE **)ptr;
00516   log->time = t;
00517   log->recvTime = recvT<0.0?0:recvT;
00518 //  log->write(fp);
00519   toProjectionsFile p(fp);
00520   log->pup(p);
00521 }
00522 #endif
00523 
00524 // flush log entries to disk
00525 void LogPool::flushLogBuffer()
00526 {
00527   if (numEntries) {
00528     double writeTime = TraceTimer();
00529     writeLog();
00530     numEntries = 0;
00531     new (&pool[numEntries++]) LogEntry(writeTime, BEGIN_INTERRUPT);
00532     new (&pool[numEntries++]) LogEntry(TraceTimer(), END_INTERRUPT);
00533   }
00534 }
00535 
00536 void LogPool::add(UChar type, UShort mIdx, UShort eIdx,
00537                   double time, int event, int pe, int ml, CmiObjId *id, 
00538                   double recvT, double cpuT, int numPe)
00539 {
00540   new (&pool[numEntries++])
00541     LogEntry(time, type, mIdx, eIdx, event, pe, ml, id, recvT, cpuT, numPe);
00542   if(poolSize==numEntries) {
00543     flushLogBuffer();
00544 #if CMK_BLUEGENE_CHARM
00545     extern int correctTimeLog;
00546     if (correctTimeLog) CmiAbort("I/O interrupt!\n");
00547 #endif
00548   }
00549 #if CMK_BLUEGENE_CHARM
00550   switch (type) {
00551     case BEGIN_PROCESSING:
00552       pool[numEntries-1].recvTime = BgGetRecvTime();
00553     case END_PROCESSING:
00554     case BEGIN_COMPUTATION:
00555     case END_COMPUTATION:
00556     case CREATION:
00557     case BEGIN_PACK:
00558     case END_PACK:
00559     case BEGIN_UNPACK:
00560     case END_UNPACK:
00561     case USER_EVENT_PAIR:
00562       bgAddProjEvent(&pool[numEntries-1], numEntries-1, time, updateProjLog, &fp, BG_EVENT_PROJ);
00563   }
00564 #endif
00565 }
00566 
00567 void LogPool::add(UChar type,double time,UShort funcID,int lineNum,char *fileName){
00568 #ifndef CMK_BLUEGENE_CHARM
00569   new (&pool[numEntries++])
00570         LogEntry(time,type,funcID,lineNum,fileName);
00571   if(poolSize == numEntries){
00572     flushLogBuffer();
00573   }
00574 #endif  
00575 }
00576 
00577 
00578   
00579 void LogPool::addMemoryUsage(unsigned char type,double time,double memUsage){
00580 #ifndef CMK_BLUEGENE_CHARM
00581   new (&pool[numEntries++])
00582         LogEntry(type,time,memUsage);
00583   if(poolSize == numEntries){
00584     flushLogBuffer();
00585   }
00586 #endif  
00587         
00588 }  
00589 
00590 
00591 
00592 
00593 void LogPool::addUserSupplied(int data){
00594         // add an event
00595         add(USER_SUPPLIED, 0, 0, TraceTimer(), -1, -1, 0, 0, 0, 0, 0 );
00596 
00597         // set the user supplied value for the previously created event 
00598         pool[numEntries-1].setUserSuppliedData(data);
00599   }
00600 
00601 /* **CW** Not sure if this is the right thing to do. Feels more like
00602    a hack than a solution to Sameer's request to add the destination
00603    processor information to multicasts and broadcasts.
00604 
00605    In the unlikely event this method is used for Broadcasts as well,
00606    pelist == NULL will be used to indicate a global broadcast with 
00607    num PEs.
00608 */
00609 void LogPool::addCreationMulticast(UShort mIdx, UShort eIdx, double time,
00610                                    int event, int pe, int ml, CmiObjId *id,
00611                                    double recvT, int numPe, int *pelist)
00612 {
00613   new (&pool[numEntries++])
00614     LogEntry(time, mIdx, eIdx, event, pe, ml, id, recvT, numPe, pelist);
00615   if(poolSize==numEntries) {
00616     flushLogBuffer();
00617   }
00618 }
00619 
00620 void LogPool::postProcessLog()
00621 {
00622 #if CMK_BLUEGENE_CHARM
00623   bgUpdateProj(1);   // event type
00624 #endif
00625 }
00626 
00628 LogEntry::LogEntry(double tm, unsigned short m, unsigned short e, int ev, int p,
00629              int ml, CmiObjId *d, double rt, int numPe, int *pelist) 
00630 {
00631     type = CREATION_MULTICAST; mIdx = m; eIdx = e; event = ev; pe = p; time = tm; msglen = ml;
00632     if (d) id = *d; else {id.id[0]=id.id[1]=id.id[2]=id.id[3]=-1; };
00633     recvTime = rt; 
00634     numpes = numPe;
00635     if (pelist != NULL) {
00636         pes = new int[numPe];
00637         for (int i=0; i<numPe; i++) {
00638           pes[i] = pelist[i];
00639         }
00640     } else {
00641         pes= NULL;
00642     }
00643 }
00644 
00645 void LogEntry::addPapi(int numPapiEvts, int *papi_ids, LONG_LONG_PAPI *papiVals)
00646 {
00647 #if CMK_HAS_COUNTER_PAPI
00648   numPapiEvents = numPapiEvts;
00649   if (papiVals != NULL) {
00650     papiIDs = new int[numPapiEvents];
00651     papiValues = new LONG_LONG_PAPI[numPapiEvents];
00652     for (int i=0; i<numPapiEvents; i++) {
00653       papiIDs[i] = papi_ids[i];
00654       papiValues[i] = papiVals[i];
00655     }
00656   }
00657 #endif
00658 }
00659 
00660 
00661 
00662 void LogEntry::pup(PUP::er &p)
00663 {
00664   int i;
00665   CMK_TYPEDEF_UINT8 itime, irecvtime, icputime;
00666   char ret = '\n';
00667 
00668   p|type;
00669   if (p.isPacking()) itime = (CMK_TYPEDEF_UINT8)(1.0e6*time);
00670   switch (type) {
00671     case USER_EVENT:
00672     case USER_EVENT_PAIR:
00673       p|mIdx; p|itime; p|event; p|pe;
00674       break;
00675     case BEGIN_IDLE:
00676     case END_IDLE:
00677     case BEGIN_PACK:
00678     case END_PACK:
00679     case BEGIN_UNPACK:
00680     case END_UNPACK:
00681       p|itime; p|pe; 
00682       break;
00683     case BEGIN_PROCESSING:
00684       if (p.isPacking()) {
00685         irecvtime = (CMK_TYPEDEF_UINT8)(recvTime==-1?-1:1.0e6*recvTime);
00686         icputime = (CMK_TYPEDEF_UINT8)(1.0e6*cputime);
00687       }
00688       p|mIdx; p|eIdx; p|itime; p|event; p|pe; 
00689       p|msglen; p|irecvtime; 
00690       p|id.id[0]; p|id.id[1]; p|id.id[2]; p|id.id[3];
00691       p|icputime;
00692 #if CMK_HAS_COUNTER_PAPI
00693       p|numPapiEvents;
00694       for (i=0; i<numPapiEvents; i++) {
00695         // not yet!!!
00696         //      p|papiIDs[i]; 
00697         p|papiValues[i];
00698         
00699       }
00700 #else
00701       p|numPapiEvents;     // non papi version has value 0
00702 #endif
00703       if (p.isUnpacking()) {
00704         recvTime = irecvtime/1.0e6;
00705         cputime = icputime/1.0e6;
00706       }
00707       break;
00708     case END_PROCESSING:
00709       if (p.isPacking()) icputime = (CMK_TYPEDEF_UINT8)(1.0e6*cputime);
00710       p|mIdx; p|eIdx; p|itime; p|event; p|pe; p|msglen; p|icputime;
00711 #if CMK_HAS_COUNTER_PAPI
00712       p|numPapiEvents;
00713       for (i=0; i<numPapiEvents; i++) {
00714         // not yet!!!
00715         //      p|papiIDs[i];
00716         p|papiValues[i];
00717       }
00718 #else
00719       p|numPapiEvents;  // non papi version has value 0
00720 #endif
00721       if (p.isUnpacking()) cputime = icputime/1.0e6;
00722       break;
00723     case USER_SUPPLIED:
00724           p|userSuppliedData;
00725           p|itime;
00726         break;
00727     case MEMORY_USAGE_CURRENT:
00728       p | memUsage;
00729       p | itime;
00730         break;
00731     case CREATION:
00732       if (p.isPacking()) irecvtime = (CMK_TYPEDEF_UINT8)(1.0e6*recvTime);
00733       p|mIdx; p|eIdx; p|itime;
00734       p|event; p|pe; p|msglen; p|irecvtime;
00735       if (p.isUnpacking()) recvTime = irecvtime/1.0e6;
00736       break;
00737     case CREATION_BCAST:
00738       if (p.isPacking()) irecvtime = (CMK_TYPEDEF_UINT8)(1.0e6*recvTime);
00739       p|mIdx; p|eIdx; p|itime;
00740       p|event; p|pe; p|msglen; p|irecvtime; p|numpes;
00741       if (p.isUnpacking()) recvTime = irecvtime/1.0e6;
00742       break;
00743     case CREATION_MULTICAST:
00744       if (p.isPacking()) irecvtime = (CMK_TYPEDEF_UINT8)(1.0e6*recvTime);
00745       p|mIdx; p|eIdx; p|itime;
00746       p|event; p|pe; p|msglen; p|irecvtime; p|numpes;
00747       if (p.isUnpacking()) pes = numpes?new int[numpes]:NULL;
00748       for (i=0; i<numpes; i++) p|pes[i];
00749       if (p.isUnpacking()) recvTime = irecvtime/1.0e6;
00750       break;
00751     case MESSAGE_RECV:
00752       p|mIdx; p|eIdx; p|itime; p|event; p|pe; p|msglen;
00753       break;
00754 
00755     case ENQUEUE:
00756     case DEQUEUE:
00757       p|mIdx; p|itime; p|event; p|pe;
00758       break;
00759 
00760     case BEGIN_INTERRUPT:
00761     case END_INTERRUPT:
00762       p|itime; p|event; p|pe;
00763       break;
00764 
00765       // **CW** absolute timestamps are used here to support a quick
00766       // way of determining the total time of a run in projections
00767       // visualization.
00768     case BEGIN_COMPUTATION:
00769     case END_COMPUTATION:
00770     case BEGIN_TRACE:
00771     case END_TRACE:
00772       p|itime;
00773       break;
00774     case BEGIN_FUNC:
00775         p | itime;
00776         p | mIdx;
00777         p | event;
00778         if(!p.isUnpacking()){
00779                 p(fName,flen-1);
00780         }
00781         break;
00782     case END_FUNC:
00783         p | itime;
00784         p | mIdx;
00785         break;
00786     default:
00787       CmiError("***Internal Error*** Wierd Event %d.\n", type);
00788       break;
00789   }
00790   if (p.isUnpacking()) time = itime/1.0e6;
00791   p|ret;
00792 }
00793 
00794 TraceProjections::TraceProjections(char **argv): 
00795   curevent(0), inEntry(0), computationStarted(0), 
00796   converseExit(0), endTime(0.0)
00797 {
00798   //  CkPrintf("Trace projections dummy constructor called on %d\n",CkMyPe());
00799 
00800   if (CkpvAccess(traceOnPe) == 0) return;
00801 
00802   CtvInitialize(int,curThreadEvent);
00803   CkpvInitialize(int, CtrLogBufSize);
00804   CkpvInitialize(bool, useOutlierAnalysis);
00805   CkpvAccess(CtrLogBufSize) = DefaultLogBufSize;
00806   CtvAccess(curThreadEvent)=0;
00807   CkpvAccess(useOutlierAnalysis) =
00808     CmiGetArgFlagDesc(argv, "+outlier", "Perform Outlier Analysis");
00809   if (CmiGetArgIntDesc(argv,"+logsize",&CkpvAccess(CtrLogBufSize), 
00810                        "Log entries to buffer per I/O")) {
00811     if (CkMyPe() == 0) {
00812       CmiPrintf("Trace: logsize: %d\n", CkpvAccess(CtrLogBufSize));
00813     }
00814   }
00815   checknested = 
00816     CmiGetArgFlagDesc(argv,"+checknested",
00817                       "check projections nest begin end execute events");
00818   int binary = 
00819     CmiGetArgFlagDesc(argv,"+binary-trace",
00820                       "Write log files in binary format");
00821 #if CMK_PROJECTIONS_USE_ZLIB
00822   int compressed = CmiGetArgFlagDesc(argv,"+gz-trace","Write log files pre-compressed with gzip");
00823 #else
00824   // consume the flag so there's no confusing
00825   CmiGetArgFlagDesc(argv,"+gz-trace",
00826                     "Write log files pre-compressed with gzip");
00827   CkPrintf("Warning: gz-trace is not supported on this machine!\n");
00828 #endif
00829 
00830   // **CW** default to non delta log encoding. The user may choose to do
00831   // create both logs (for debugging) or just the old log timestamping
00832   // (for compatibility).
00833   // Generating just the non delta log takes precedence over generating
00834   // both logs (if both arguments appear on the command line).
00835 
00836   // switch to OLD log format until everything works // Gengbin
00837   nonDeltaLog = 1;
00838   deltaLog = 0;
00839   deltaLog = CmiGetArgFlagDesc(argv, "+logDelta",
00840                                   "Generate Delta encoded and simple timestamped log files");
00841 
00842   _logPool = new LogPool(CkpvAccess(traceRoot));
00843   _logPool->setBinary(binary);
00844 #if CMK_PROJECTIONS_USE_ZLIB
00845   _logPool->setCompressed(compressed);
00846 #endif
00847   if (CkMyPe() == 0) {
00848     _logPool->createSts();
00849     _logPool->createRC();
00850   }
00851   funcCount=1;
00852 
00853 #if CMK_HAS_COUNTER_PAPI
00854   // We initialize and create the event sets for use with PAPI here.
00855   int papiRetValue = PAPI_library_init(PAPI_VER_CURRENT);
00856   if (papiRetValue != PAPI_VER_CURRENT) {
00857     CmiAbort("PAPI Library initialization failure!\n");
00858   }
00859   // PAPI 3 mandates the initialization of the set to PAPI_NULL
00860   papiEventSet = PAPI_NULL; 
00861   if (PAPI_create_eventset(&papiEventSet) != PAPI_OK) {
00862     CmiAbort("PAPI failed to create event set!\n");
00863   }
00864   papiRetValue = PAPI_add_events(papiEventSet, papiEvents, numPAPIEvents);
00865   if (papiRetValue != PAPI_OK) {
00866     if (papiRetValue == PAPI_ECNFLCT) {
00867       CmiAbort("PAPI events conflict! Please re-assign event types!\n");
00868     } else {
00869       CmiAbort("PAPI failed to add designated events!\n");
00870     }
00871   }
00872   papiValues = new long_long[numPAPIEvents];
00873   memset(papiValues, 0, numPAPIEvents*sizeof(long_long));
00874 #endif
00875 }
00876 
00877 int