src/Profile/Profiler.cpp

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  * This program was prepared by PSI. 
00007  * All rights in the program are reserved by PSI.
00008  * Neither PSI nor the author(s)
00009  * makes any warranty, express or implied, or assumes any liability or
00010  * responsibility for the use of this software
00011  *
00012  * Visit http://www.acl.lanl.gov/POOMS for more details
00013  *
00014  ***************************************************************************/
00015 
00016 // -*- C++ -*-
00017 /***************************************************************************
00018  *
00019  * The IPPL Framework
00020  * 
00021  * This program was prepared by PSI. 
00022  * All rights in the program are reserved by PSI.
00023  * Neither PSI nor the author(s)
00024  * makes any warranty, express or implied, or assumes any liability or
00025  * responsibility for the use of this software
00026  *
00027  * Visit http://www.acl.lanl.gov/POOMS for more details
00028  *
00029  ***************************************************************************/
00030 
00031 /****************************************************************************
00032 **                      TAU Portable Profiling Package                     **
00033 **                      http://www.acl.lanl.gov/tau                        **
00034 *****************************************************************************
00035 **    Copyright 1997                                                       **
00036 **    Department of Computer and Information Science, University of Oregon **
00037 **    Advanced Computing Laboratory, Los Alamos National Laboratory        **
00038 ****************************************************************************/
00039 /***************************************************************************
00040 **      File            : Profiler.cpp                                    **
00041 **      Description     : TAU Profiling Package                           **
00042 **      Author          : Sameer Shende                                   **
00043 **      Contact         : sameer@cs.uoregon.edu sameer@acl.lanl.gov       **
00044 **      Flags           : Compile with                                    **
00045 **                        -DPROFILING_ON to enable profiling (ESSENTIAL)  **
00046 **                        -DPROFILE_STATS for Std. Deviation of Excl Time **
00047 **                        -DSGI_HW_COUNTERS for using SGI counters        **
00048 **                        -DPROFILE_CALLS  for trace of each invocation   **
00049 **                        -DSGI_TIMERS  for SGI fast nanosecs timer       **
00050 **                        -DTULIP_TIMERS for non-sgi Platform             **
00051 **                        -DIPPL_STDSTL for using STD STL in IPPL src   **
00052 **                        -DIPPL_TFLOP for Intel Teraflop at SNL/NM       **
00053 **                        -DIPPL_KAI for KCC compiler                     **
00054 **                        -DDEBUG_PROF  for internal debugging messages   **
00055 **      Documentation   : See http://www.acl.lanl.gov/tau                 **
00056 ***************************************************************************/
00057 
00059 // Include Files 
00061 
00062 #include "Profile/Profiler.h"
00063 
00064 
00065 #ifdef IPPL_USE_STANDARD_HEADERS
00066 #include <iostream>
00067 using namespace std;
00068 #else
00069 #include <iostream.h>
00070 #endif
00071 
00072 #include <stdio.h> 
00073 #include <fcntl.h>
00074 #include <time.h>
00075 #include <unistd.h>
00076 #include <stdlib.h>
00077 #include <string.h>
00078 
00079 #if (defined(IPPL_TFLOP) || !defined(TULIP_TIMERS))
00080 #include <sys/time.h>
00081 #else
00082 #ifdef TULIP_TIMERS 
00083 #include "Profile/TulipTimers.h"
00084 #endif //TULIP_TIMERS 
00085 #endif //IPPL_TFLOP
00086 
00087 #ifdef TRACING_ON
00088 #define PCXX_EVENT_SRC
00089 #include "pcxx_events.h"
00090 #endif // TRACING_ON 
00091 
00092 //#define PROFILE_CALLS // Generate Excl Incl data for each call 
00093 //#define DEBUG_PROF // For Debugging Messages from Profiler.cpp
00094 
00095 #ifdef DEBUG_PROF
00096 #define DEBUGPROFMSG(msg) { cout<< msg; }
00097 #else
00098 #define DEBUGPROFMSG(msg) 
00099 #endif // DEBUG_PROF
00100 
00102 //Initialize static data
00104 
00105 vector<FunctionInfo*> FunctionInfo::FunctionDB[TAU_MAX_THREADS] ;
00106 Profiler * Profiler::CurrentProfiler[] = {0}; // null to start with
00107 // The rest of CurrentProfiler entries are initialized to null automatically
00108 unsigned int RtsLayer::ProfileMask = TAU_DEFAULT;
00109 
00110 // Default value of Node.
00111 int RtsLayer::Node = -1;
00112 
00114 // Explicit Instantiations for templated entities needed for ASCI Red
00116 
00117 #ifdef IPPL_TFLOP
00118 template void vector<FunctionInfo *>::insert_aux(vector<FunctionInfo *>::pointer, FunctionInfo *const &);
00119 #ifndef IPPL_STDSTL
00120 // need a few other function templates instantiated
00121 template FunctionInfo** copy_backward(FunctionInfo**,FunctionInfo**,FunctionInfo**);
00122 template FunctionInfo** uninitialized_copy(FunctionInfo**,FunctionInfo**,FunctionInfo**);
00123 #endif // not IPPL_STDSTL
00124 #endif //IPPL_TFLOP
00125 
00127 // Member Function Definitions For class FunctionInfo
00129 
00131 FunctionInfo::FunctionInfo(const char *name, const char *type, 
00132         unsigned int ProfileGroup , const char *ProfileGroupName)
00133 {
00134       if (ProfileGroup & RtsLayer::ProfileMask) {
00135 
00136         Name = name;
00137         Type = type;
00138 #ifdef TRACING_ON
00139         GroupName = RtsLayer::PrimaryGroup(ProfileGroupName);
00140 #endif //TRACING_ON
00141         NumCalls = 0;
00142         NumSubrs = 0;
00143         ExclTime = 0;
00144         InclTime = 0;
00145 
00146 // Since FunctionInfo constructor is called once for each function (static)
00147 // we know that it couldn't be already on the call stack.
00148         SetAlreadyOnStack(false);
00149 
00150 #ifdef PROFILE_STATS
00151         SumExclSqr = 0;
00152 #endif //PROFILE_STATS
00153 
00154 #ifdef PROFILE_CALLS
00155         ExclInclCallList = new list<pair<double, double> >();
00156 #endif //PROFILE_CALLS
00157         // Make this a ptr to a list so that ~FunctionInfo doesn't destroy it.
00158         
00159         MyProfileGroup_ = ProfileGroup ;
00160         FunctionDB[RtsLayer::myThread()].push_back(this);
00161 #ifdef TRACING_ON
00162         // Function Id is the index into the DB vector
00163         FunctionId = FunctionDB[RtsLayer::myThread()].size();
00164 #endif //TRACING_ON
00165                 
00166         DEBUGPROFMSG("Thr "<< RtsLayer::myNode() 
00167           << " FunctionInfo::FunctionInfo(n,t) : Name : "<< GetName() 
00168           << " Type : " << GetType() << endl;);
00169       }
00170 }
00171 
00173 
00174 FunctionInfo::FunctionInfo(string& name, const char* type, 
00175         unsigned int ProfileGroup , const char *ProfileGroupName)
00176 {
00177       if (ProfileGroup & RtsLayer::ProfileMask) {
00178 
00179         Name = name;
00180         Type = type;
00181 #ifdef TRACING_ON
00182         GroupName = RtsLayer::PrimaryGroup(ProfileGroupName);
00183 #endif //TRACING_ON 
00184         NumCalls = 0;
00185         NumSubrs = 0;
00186         ExclTime = 0;
00187         InclTime = 0;
00188 
00189 // Since FunctionInfo constructor is called once for each function (static)
00190 // we know that it couldn't be already on the call stack.
00191         SetAlreadyOnStack(false);
00192 
00193 #ifdef PROFILE_STATS
00194         SumExclSqr = 0;
00195 #endif //PROFILE_STATS
00196 
00197 #ifdef PROFILE_CALLS
00198         ExclInclCallList = new list<pair<double, double> >();
00199 #endif //PROFILE_CALLS
00200         // Make this a ptr to a list so that ~FunctionInfo doesn't destroy it.
00201         
00202         MyProfileGroup_ = ProfileGroup ;
00203         FunctionDB[RtsLayer::myThread()].push_back(this);
00204 #ifdef TRACING_ON
00205         // Function Id is the index into the DB vector
00206         FunctionId = FunctionDB[RtsLayer::myThread()].size();
00207 #endif //TRACING_ON
00208                 
00209         DEBUGPROFMSG("Thr "<< RtsLayer::myNode() 
00210           << " FunctionInfo::FunctionInfo(n,t) : Name : "<< GetName() 
00211           << " Type : " << GetType() << endl;);
00212       }
00213 }
00214 
00216 
00217 FunctionInfo::FunctionInfo(const char *name, string& type, 
00218         unsigned int ProfileGroup , const char *ProfileGroupName)
00219 {
00220       if (ProfileGroup & RtsLayer::ProfileMask) {
00221 
00222         Name = name;
00223         Type = type;
00224 #ifdef TRACING_ON
00225         GroupName = RtsLayer::PrimaryGroup(ProfileGroupName);
00226 #endif //TRACING_ON 
00227         NumCalls = 0;
00228         NumSubrs = 0;
00229         ExclTime = 0;
00230         InclTime = 0;
00231 
00232 // Since FunctionInfo constructor is called once for each function (static)
00233 // we know that it couldn't be already on the call stack.
00234         SetAlreadyOnStack(false);
00235 
00236 #ifdef PROFILE_STATS
00237         SumExclSqr = 0;
00238 #endif //PROFILE_STATS
00239 
00240 #ifdef PROFILE_CALLS
00241         ExclInclCallList = new list<pair<double, double> >();
00242 #endif //PROFILE_CALLS
00243         // Make this a ptr to a list so that ~FunctionInfo doesn't destroy it.
00244         
00245         MyProfileGroup_ = ProfileGroup ;
00246         FunctionDB[RtsLayer::myThread()].push_back(this);
00247 #ifdef TRACING_ON
00248         // Function Id is the index into the DB vector
00249         FunctionId = FunctionDB[RtsLayer::myThread()].size();
00250 #endif //TRACING_ON
00251                 
00252         DEBUGPROFMSG("Thr "<< RtsLayer::myNode() 
00253           << " FunctionInfo::FunctionInfo(n,t) : Name : "<< GetName() 
00254           << " Type : " << GetType() << endl;);
00255       }
00256 }
00257 
00259 
00260 FunctionInfo::FunctionInfo(string& name, string& type, 
00261         unsigned int ProfileGroup , const char *ProfileGroupName)
00262 {
00263       if (ProfileGroup & RtsLayer::ProfileMask) {
00264 
00265         Name = name;
00266         Type = type;
00267 #ifdef TRACING_ON
00268         GroupName = RtsLayer::PrimaryGroup(ProfileGroupName);
00269 #endif //TRACING_ON 
00270         NumCalls = 0;
00271         NumSubrs = 0;
00272         ExclTime = 0;
00273         InclTime = 0;
00274 
00275 // Since FunctionInfo constructor is called once for each function (static)
00276 // we know that it couldn't be already on the call stack.
00277         SetAlreadyOnStack(false);
00278 
00279 #ifdef PROFILE_STATS
00280         SumExclSqr = 0;
00281 #endif //PROFILE_STATS
00282 
00283 #ifdef PROFILE_CALLS
00284         ExclInclCallList = new list<pair<double, double> >();
00285 #endif //PROFILE_CALLS
00286         // Make this a ptr to a list so that ~FunctionInfo doesn't destroy it.
00287         
00288         MyProfileGroup_ = ProfileGroup ;
00289         FunctionDB[RtsLayer::myThread()].push_back(this);
00290 #ifdef TRACING_ON
00291         // Function Id is the index into the DB vector
00292         FunctionId = FunctionDB[RtsLayer::myThread()].size();
00293 #endif //TRACING_ON
00294                 
00295         DEBUGPROFMSG("Thr "<< RtsLayer::myNode() 
00296           << " FunctionInfo::FunctionInfo(n,t) : Name : "<< GetName() 
00297           << " Type : " << GetType() << endl;);
00298       }
00299 }
00300 
00302 
00303 FunctionInfo::FunctionInfo(const FunctionInfo& X) 
00304 : Name(X.Name),
00305   Type(X.Type),
00306   NumCalls(X.NumCalls),
00307   NumSubrs(X.NumSubrs),
00308   ExclTime(X.ExclTime),
00309   InclTime(X.InclTime),
00310   MyProfileGroup_(X.MyProfileGroup_) 
00311 {
00312         DEBUGPROFMSG("FunctionInfo::FunctionInfo (const FunctionInfo& X)"<<endl;);
00313         FunctionDB[RtsLayer::myThread()].push_back(this);
00314 }
00316 
00317 FunctionInfo& FunctionInfo::operator= (const FunctionInfo& X) 
00318 {
00319         DEBUGPROFMSG("FunctionInfo::operator= (const FunctionInfo& X)" << endl;);
00320         Name = X.Name;
00321         Type = X.Type;
00322         NumCalls = X.NumCalls;
00323         NumSubrs = X.NumSubrs;
00324         ExclTime = X.ExclTime;
00325         InclTime = X.InclTime;
00326         MyProfileGroup_ = X.MyProfileGroup_;
00327         return (*this);
00328 }
00329 
00331 
00332 FunctionInfo::~FunctionInfo()
00333 {
00334 // Don't delete Name, Type - if dtor of static object dumps the data
00335 // after all these function objects are destroyed, it can't get the 
00336 // name, and type.
00337 //      delete [] Name;
00338 //      delete [] Type;
00339 }
00340 
00341 #ifdef PROFILE_CALLS
00342 
00343 
00344 int FunctionInfo::AppendExclInclTimeThisCall(double ex, double in)
00345 {
00346         ExclInclCallList->push_back(pair<double,double>(ex,in));
00347         return 1;
00348 }
00349 
00350 #endif //PROFILE_CALLS
00351 
00352  
00354 // Member Function Definitions For class Profiler
00356 
00358 
00359 void Profiler::Start(void)
00360 { 
00361      
00362       if (MyProfileGroup_ & RtsLayer::ProfileMask) {
00363         
00364 #ifdef TRACING_ON
00365         pcxx_Event(ThisFunction->GetFunctionId(), 1); // 1 is for entry
00366 #endif /* TRACING_ON */
00367 
00368 #ifdef PROFILING_ON
00369         // First, increment the number of calls
00370         ThisFunction->IncrNumCalls();
00371         
00372         // Next, if this function is not already on the call stack, put it
00373         if (ThisFunction->GetAlreadyOnStack() == false)   { 
00374           AddInclFlag = true; 
00375           // We need to add Inclusive time when it gets over as 
00376           // it is not already on callstack.
00377 
00378           ThisFunction->SetAlreadyOnStack(true); // it is on callstack now
00379         }
00380         else { // the function is already on callstack, no need to add
00381                // inclusive time
00382           AddInclFlag = false;
00383         }
00384         
00385         // Initialization is over, now record the time it started
00386         StartTime =  RtsLayer::getUSecD() ;
00387 #endif // PROFILING_ON
00388         ParentProfiler = CurrentProfiler[RtsLayer::myThread()] ;
00389 
00390         DEBUGPROFMSG("Thr " << RtsLayer::myNode() <<
00391           " Profiler::Start (FunctionInfo * f)  : Name : " << 
00392           ThisFunction->GetName() <<" Type : " << ThisFunction->GetType() 
00393           << endl; );
00394 
00395         CurrentProfiler[RtsLayer::myThread()] = this;
00396 
00397 #if ( defined(PROFILE_CALLS) || defined(PROFILE_STATS) )
00398         ExclTimeThisCall = 0;
00399 #endif //PROFILE_CALLS || PROFILE_STATS
00400       }  
00401 }
00402 
00404 
00405 Profiler::Profiler( FunctionInfo * function, unsigned int ProfileGroup, bool StartStop)
00406 {
00407       StartStopUsed_ = StartStop; // will need it later in ~Profiler
00408       MyProfileGroup_ = ProfileGroup ;
00409       ThisFunction = function ; 
00410       ParentProfiler = CurrentProfiler[RtsLayer::myThread()]; // Timers
00411       
00412       if(!StartStopUsed_) { // Profiler ctor/dtor interface used
00413         Start(); 
00414       }
00415 }
00416 
00417 
00419 
00420 Profiler::Profiler( const Profiler& X)
00421 : StartTime(X.StartTime),
00422   ThisFunction(X.ThisFunction),
00423   ParentProfiler(X.ParentProfiler),
00424   MyProfileGroup_(X.MyProfileGroup_),
00425   StartStopUsed_(X.StartStopUsed_)
00426 {
00427         DEBUGPROFMSG("Profiler::Profiler(const Profiler& X)"<<endl;);
00428 
00429         CurrentProfiler[RtsLayer::myThread()] = this;
00430 
00431 #if ( defined(PROFILE_CALLS) || defined(PROFILE_STATS) )
00432         ExclTimeThisCall = X.ExclTimeThisCall;
00433 #endif //PROFILE_CALLS || PROFILE_STATS
00434 }
00435 
00437 
00438 Profiler& Profiler::operator= (const Profiler& X)
00439 {
00440         StartTime = X.StartTime;
00441         ThisFunction = X.ThisFunction;
00442         ParentProfiler = X.ParentProfiler; 
00443         MyProfileGroup_ = X.MyProfileGroup_;
00444         StartStopUsed_ = X.StartStopUsed_;
00445 
00446         DEBUGPROFMSG(" Profiler& Profiler::operator= (const Profiler& X)" <<endl;);
00447 
00448 #if ( defined(PROFILE_CALLS) || defined(PROFILE_STATS) )
00449         ExclTimeThisCall = X.ExclTimeThisCall;
00450 #endif //PROFILE_CALLS || PROFILE_STATS
00451 
00452         return (*this) ;
00453 
00454 }
00455 
00457 
00458 void Profiler::Stop()
00459 {
00460       if (MyProfileGroup_ & RtsLayer::ProfileMask) {
00461 
00462 #ifdef TRACING_ON
00463         pcxx_Event(ThisFunction->GetFunctionId(), -1); // -1 is for exit 
00464 #endif //TRACING_ON
00465 
00466 #ifdef PROFILING_ON  // Calculations relevent to profiling only 
00467         double TotalTime = RtsLayer::getUSecD() - StartTime;
00468 
00469         DEBUGPROFMSG("Thr "<< RtsLayer::myNode() 
00470           << " Profiler::Stop() : Name : "<< ThisFunction->GetName() 
00471           << " Start : " <<StartTime <<" TotalTime : " << TotalTime<< endl;);
00472 
00473         if (AddInclFlag == true) { // The first time it came on call stack
00474           ThisFunction->SetAlreadyOnStack(false); // while exiting
00475 
00476           // And its ok to add both excl and incl times
00477           ThisFunction->AddInclTime(TotalTime);
00478           DEBUGPROFMSG("Thr "<< RtsLayer::myNode()
00479             << " AddInclFlag true in Stop Name: "<< ThisFunction->GetName()
00480             << " Type: " << ThisFunction->GetType() << endl; );
00481         } 
00482         // If its already on call stack, don't change AlreadyOnStack
00483         ThisFunction->AddExclTime(TotalTime);
00484         // In either case we need to add time to the exclusive time.
00485 
00486 #if ( defined(PROFILE_CALLS) || defined(PROFILE_STATS) )
00487         ExclTimeThisCall += TotalTime;
00488         DEBUGPROFMSG("Thr "<< RtsLayer::myNode() << "Profiler::Stop() : Name " 
00489           << ThisFunction->GetName() << " ExclTimeThisCall = "
00490           << ExclTimeThisCall << " InclTimeThisCall " << TotalTime << endl;);
00491 
00492 #endif //PROFILE_CALLS || PROFILE_STATS
00493 
00494 #ifdef PROFILE_CALLS
00495         ThisFunction->AppendExclInclTimeThisCall(ExclTimeThisCall, TotalTime);
00496 #endif // PROFILE_CALLS
00497 
00498 #ifdef PROFILE_STATS
00499         ThisFunction->AddSumExclSqr(ExclTimeThisCall*ExclTimeThisCall);
00500 #endif // PROFILE_STATS
00501 
00502         if (ParentProfiler != 0) {
00503 
00504           DEBUGPROFMSG("Thr " << RtsLayer::myNode() 
00505             << " Profiler::Stop(): ParentProfiler Function Name : " 
00506             << ParentProfiler->ThisFunction->GetName() << endl;);
00507 
00508           ParentProfiler->ThisFunction->ExcludeTime(TotalTime);
00509 #if ( defined(PROFILE_CALLS) || defined(PROFILE_STATS) )
00510           ParentProfiler->ExcludeTimeThisCall(TotalTime);
00511 #endif //PROFILE_CALLS || PROFILE_STATS
00512 
00513         }
00514         
00515 #endif //PROFILING_ON
00516         // First check if timers are overlapping.
00517         if (CurrentProfiler[RtsLayer::myThread()] != this) {
00518           cout <<"ERROR: Timers Overlap. Illegal operation Profiler::Stop " 
00519           << ThisFunction->GetName() << " " << ThisFunction->GetType() <<endl;
00520         }
00521         // While exiting, reset value of CurrentProfiler to reflect the parent
00522         CurrentProfiler[RtsLayer::myThread()] = ParentProfiler;
00523 
00524       } // if ProfileMask 
00525 }
00526 
00528 
00529 Profiler::~Profiler() {
00530 
00531      if (!StartStopUsed_) {
00532         Stop();
00533       } // If ctor dtor interface is used then call Stop. 
00534         // If the Profiler object is going out of scope without Stop being
00535         // called, call it now!
00536 
00537       if (MyProfileGroup_ & RtsLayer::ProfileMask) {
00538         if (ParentProfiler == 0) {
00539           if (!RtsLayer::isCtorDtor(ThisFunction->GetName())) {
00540           // Not a destructor of a static object - its a function like main 
00541             DEBUGPROFMSG("Thr " << RtsLayer::myNode() 
00542               << " ~Profiler() : Reached top level function - dumping data" 
00543               << endl;);
00544 
00545             StoreData();
00546           }
00547         // dump data here. Dump it only in the dtor of top level profiler. 
00548         }
00549       }
00550 }
00551 
00553 
00554 void Profiler::ProfileExit(const char *message)
00555 {
00556   Profiler *current;
00557 
00558   current = CurrentProfiler[RtsLayer::myThread()];
00559 
00560   DEBUGPROFMSG("Thr "<< RtsLayer::myNode() << " RtsLayer::ProfileExit called :"
00561     << message << endl;);
00562 
00563   while (current != 0) {
00564     DEBUGPROFMSG("Thr "<< RtsLayer::myNode() << " ProfileExit() calling Stop :" 
00565       << current->ThisFunction->GetName() << " " 
00566       << current->ThisFunction->GetType() << endl;);
00567     current->Stop(); // clean up 
00568 
00569     if (current->ParentProfiler == 0) {
00570       if (!RtsLayer::isCtorDtor(current->ThisFunction->GetName())) {
00571        // Not a destructor of a static object - its a function like main
00572          DEBUGPROFMSG("Thr " << RtsLayer::myNode()
00573            << " ProfileExit() : Reached top level function - dumping data"
00574            << endl;);
00575 
00576           current->StoreData();
00577       }
00578     }
00579 
00580     current = CurrentProfiler[RtsLayer::myThread()]; // Stop should set it
00581   }
00582 
00583 }
00584 
00586 
00587 int Profiler::StoreData()
00588 {
00589 #ifdef PROFILING_ON 
00590         vector<FunctionInfo*>::iterator it;
00591         char filename[1024], errormsg[1024];
00592         char *dirname;
00593         FILE* fp;
00594         int numFunc;
00595 #endif //PROFILING_ON
00596 #ifdef PROFILE_CALLS
00597         long listSize, numCalls;
00598         list<pair<double,double> >::iterator iter;
00599 #endif // PROFILE_CALLS
00600 
00601 
00602 #ifdef TRACING_ON
00603         pcxx_EvClose();
00604         RtsLayer::DumpEDF();
00605 #endif // TRACING_ON 
00606 
00607 #ifdef PROFILING_ON 
00608         if ((dirname = getenv("PROFILEDIR")) == NULL) {
00609         // Use default directory name .
00610            dirname  = new char[8];
00611            strcpy (dirname,".");
00612         }
00613          
00614         sprintf(filename,"%s/profile.%d.%d.%d",dirname, RtsLayer::myNode(),
00615                 RtsLayer::myContext(), RtsLayer::myThread());
00616         DEBUGPROFMSG("Creating " << filename << endl;);
00617         if ((fp = fopen (filename, "w+")) == NULL) {
00618                 sprintf(errormsg,"Error: Could not create %s",filename);
00619                 perror(errormsg);
00620                 return 0;
00621         }
00622 
00623         // Data format :
00624         // %d templated_functions
00625         // "%s %s" %ld %G %G  
00626         //  funcname type numcalls Excl Incl
00627         // %d aggregates
00628         // <aggregate info>
00629        
00630         // Recalculate number of funcs using ProfileGroup. Static objects 
00631         // constructed before setting Profile Groups have entries in FuncDB 
00632         // (TAU_DEFAULT) even if they are not supposed to be there.
00633         //numFunc = (int) FunctionInfo::FunctionDB[RtsLayer::myThread()].size();
00634         numFunc = 0;
00635         for (it = FunctionInfo::FunctionDB[RtsLayer::myThread()].begin(); it != FunctionInfo::FunctionDB[RtsLayer::myThread()].end(); it++)
00636         {
00637           if ((*it)->GetProfileGroup() & RtsLayer::ProfileMask) { 
00638             numFunc++;
00639           }
00640         }
00641 
00642 #ifdef SGI_HW_COUNTERS
00643         fprintf(fp,"%d templated_functions_hw_counters\n", numFunc);
00644 #else  // SGI_TIMERS, TULIP_TIMERS 
00645         fprintf(fp,"%d templated_functions\n", numFunc);
00646 #endif // SGI_HW_COUNTERS 
00647 
00648         // Send out the format string
00649         fprintf(fp,"# Name Calls Subrs Excl Incl ");
00650 #ifdef PROFILE_STATS
00651         fprintf(fp,"SumExclSqr ");
00652 #endif //PROFILE_STATS
00653         fprintf(fp,"ProfileCalls\n");
00654         
00655         
00656         for (it = FunctionInfo::FunctionDB[RtsLayer::myThread()].begin(); it != FunctionInfo::FunctionDB[RtsLayer::myThread()].end(); it++)
00657         {
00658           if ((*it)->GetProfileGroup() & RtsLayer::ProfileMask) { 
00659   
00660             DEBUGPROFMSG("Node: "<< RtsLayer::myNode() <<  " Dumping " 
00661               << (*it)->GetName()<< " "  << (*it)->GetType() << " Calls : " 
00662               << (*it)->GetCalls() << " Subrs : "<< (*it)->GetSubrs() 
00663               << " Excl : " << (*it)->GetExclTime() << " Incl : " 
00664               << (*it)->GetInclTime() << endl;);
00665         
00666             fprintf(fp,"\"%s %s\" %ld %ld %.16G %.16G ", (*it)->GetName(), 
00667               (*it)->GetType(), (*it)->GetCalls(), (*it)->GetSubrs(), 
00668               (*it)->GetExclTime(), (*it)->GetInclTime());
00669   
00670 #ifdef PROFILE_STATS 
00671             fprintf(fp,"%.16G ", (*it)->GetSumExclSqr());
00672 #endif //PROFILE_STATS
00673   
00674 #ifdef PROFILE_CALLS
00675             listSize = (long) (*it)->ExclInclCallList->size(); 
00676             numCalls = (*it)->GetCalls();
00677             // Sanity check
00678             if (listSize != numCalls) 
00679             {
00680               fprintf(fp,"0 \n"); // don't write any invocation data
00681               DEBUGPROFMSG("Error *** list (profileCalls) size mismatch size "
00682                 << listSize << " numCalls " << numCalls << endl;);
00683             }
00684             else { // List is maintained correctly
00685               fprintf(fp,"%ld \n", listSize); // no of records to follow
00686               for (iter = (*it)->ExclInclCallList->begin(); 
00687                 iter != (*it)->ExclInclCallList->end(); iter++)
00688               {
00689                 DEBUGPROFMSG("Node: " << RtsLayer::myNode() <<" Name "
00690                   << (*it)->GetName() << " " << (*it)->GetType()
00691                   << " ExclThisCall : "<< (*iter).first <<" InclThisCall : " 
00692                   << (*iter).second << endl; );
00693                 fprintf(fp,"%G %G\n", (*iter).first , (*iter).second);
00694               }
00695             } // sanity check 
00696 #else  // PROFILE_CALLS
00697             fprintf(fp,"0 \n"); // Indicating - profile calls is turned off 
00698 #endif // PROFILE_CALLS
00699           } // ProfileGroup test 
00700         } // for loop. End of FunctionInfo data
00701         fprintf(fp,"0 aggregates\n"); // For now there are no aggregates
00702         // Change this when aggregate profiling in introduced in Ippl 
00703 
00704         fclose(fp);
00705 
00706 #endif //PROFILING_ON
00707         return 1;
00708 }
00709 
00711 
00712 #if ( defined(PROFILE_CALLS) || defined(PROFILE_STATS) )
00713 int Profiler::ExcludeTimeThisCall(double t)
00714 {
00715         ExclTimeThisCall -= t;
00716         return 1;
00717 }
00718 #endif //PROFILE_CALLS || PROFILE_STATS
00719 
00721 
00723 // Member Function Definitions For class RtsLayer
00724 // Important for Porting to other platforms and frameworks.
00726 
00728 
00729 unsigned int RtsLayer::enableProfileGroup(unsigned int ProfileGroup) {
00730   ProfileMask |= ProfileGroup; // Add it to the mask
00731   DEBUGPROFMSG("enableProfileGroup " << ProfileGroup <<" Mask = " << ProfileMask << endl;);
00732   return ProfileMask;
00733 }
00734 
00736 
00737 unsigned int RtsLayer::resetProfileGroup(void) {
00738   ProfileMask = 0;
00739   return ProfileMask;
00740 }
00741 
00743 int RtsLayer::setMyNode(int NodeId) {
00744   Node  = NodeId;
00745 // At this stage, we should create the trace file because we know the node id
00746 #ifdef TRACING_ON
00747   char *dirname, tracefilename[1024];
00748   if ((dirname = getenv("TRACEDIR")) == NULL) {
00749   // Use default directory name .
00750     dirname  = new char[8];
00751     strcpy (dirname,".");
00752   }
00753   sprintf(tracefilename, "%s/tau.####.trc",dirname); 
00754   pcxx_EvInit(tracefilename);
00755 #endif // TRACING_ON
00756   return Node;
00757 }
00758 
00760 
00761 bool RtsLayer::isEnabled(unsigned int ProfileGroup) {
00762 unsigned int res =  ProfileGroup & ProfileMask ;
00763 
00764   if (res > 0)
00765     return true;
00766   else
00767     return false;
00768 }
00769 
00771 
00772 #ifdef SGI_HW_COUNTERS 
00773 extern "C" {
00774   int start_counters( int e0, int e1 );
00775   int read_counters( int e0, long long *c0, int e1, long long *c1);
00776 };
00777 #endif // SGI_HW_COUNTERS
00778 
00780 #ifdef SGI_HW_COUNTERS 
00781 int RtsLayer::SetEventCounter()
00782 {
00783   int e0, e1;
00784   int start;
00785 
00786 
00787   e0 = 0;
00788   e1 = 0;
00789 
00790 
00791 //  int x0, x1;
00792   // 
00793   // DO NOT remove the following two lines. Otherwise start_counters 
00794   // crashes with "prioctl PIOCENEVCTRS returns error: Invalid argument"
00795 
00796 /*
00797   x0 = e0; 
00798   x1 = e1; 
00799 */
00800 
00801   if((start = start_counters(e0,e1)) < 0) {
00802     perror("start_counters");
00803     exit(0);
00804   }
00805   return start;
00806 }
00807 #endif // SGI_HW_COUNTERS
00808 
00810 #ifdef SGI_HW_COUNTERS 
00811 double RtsLayer::GetEventCounter()
00812 {
00813   static int gen_start = SetEventCounter();
00814   int gen_read;
00815   int e0 = 0, e1 = 0;
00816   long long c0 , c1 ;
00817   static double accum = 0;
00818 
00819   if ((gen_read = read_counters(e0, &c0, e1, &c1)) < 0) {
00820     perror("read_counters");
00821   }
00822 
00823   if (gen_read != gen_start) {
00824     perror("lost counter! aborting...");
00825     exit(1);
00826   }
00827 
00828   accum += c0;
00829   DEBUGPROFMSG("Read counters e0 " << e0 <<" e1 "<< e1<<" gen_read " 
00830     << gen_read << " gen_start = " << gen_start << " accum "<< accum 
00831     << " c0 " << c0 << " c1 " << c1 << endl;);
00832   gen_start = SetEventCounter(); // Reset the counter
00833 
00834   return accum;
00835 }
00836 #endif //SGI_HW_COUNTERS
00837 
00839 
00840 double RtsLayer::getUSecD () {
00841 
00842 #ifdef SGI_HW_COUNTERS
00843   return RtsLayer::GetEventCounter();
00844 #else  //SGI_HW_COUNTERS
00845 
00846 #ifdef SGI_TIMERS
00847   struct timespec tp;
00848   clock_gettime(CLOCK_SGI_CYCLE,&tp);
00849   return (tp.tv_sec * 1e6 + (tp.tv_nsec * 1e-3)) ;
00850 
00851 #else 
00852 #if (defined(IPPL_TFLOP) || !defined(TULIP_TIMERS)) 
00853   struct timeval tp;
00854   gettimeofday (&tp, 0);
00855   return ( tp.tv_sec * 1000000 + tp.tv_usec );
00856 #else  // TULIP_TIMERS by default.  
00857   return pcxx_GetUSecD();
00858 #endif  //IPPL_TFLOP
00859 #endif  //SGI_TIMERS
00860 
00861 #endif  // SGI_HW_COUNTERS
00862         }
00863 
00865 //Note: This is similar to Tulip event classes during tracing
00866 int RtsLayer::setAndParseProfileGroups(char *prog, char *str)
00867 {
00868   char *end;
00869   
00870   if (str) { 
00871     while (str && *str) {
00872       if ( ( end = strchr(str, '+') ) != NULL ) *end = '\0';
00873       switch (str[0])
00874       {
00875         case 'a' :
00876         case 'A' : // Assign or ACLMPL Group
00877           if (strncasecmp(str,"ac", 2) == 0) {
00878             // ACLMPL enabled 
00879             RtsLayer::enableProfileGroup(TAU_ACLMPL); 
00880           } 
00881           else {
00882             // Assign enabled 
00883             RtsLayer::enableProfileGroup(TAU_ASSIGN);
00884           }
00885           break;
00886         case 'f' :
00887         case 'F' : // Field or FFT Group
00888           if (strncasecmp(str, "ff", 2) == 0) {
00889             // FFT enabled 
00890             RtsLayer::enableProfileGroup(TAU_FFT);
00891           }
00892           else {
00893             // Field enabled 
00894             RtsLayer::enableProfileGroup(TAU_FIELD);
00895           }
00896           break;
00897         case 'c' :
00898         case 'C' : // Communication Group
00899           RtsLayer::enableProfileGroup(TAU_COMMUNICATION);
00900           break;
00901         case 'i' :
00902         case 'I' : // IO Group
00903           RtsLayer::enableProfileGroup(TAU_IO);
00904           break;
00905         case 'l' :
00906         case 'L' : // Field Layout Group
00907           RtsLayer::enableProfileGroup(TAU_LAYOUT);
00908           break;
00909         case 'm' : 
00910         case 'M' : // Mesh or Message Group
00911           if (strncasecmp(str,"mesh", 4) == 0) {
00912             // Meshes enabled
00913             RtsLayer::enableProfileGroup(TAU_MESHES);
00914           } 
00915           else {
00916             // Message Profile Group enabled 
00917             RtsLayer::enableProfileGroup(TAU_MESSAGE);
00918           }
00919           break;
00920         case 'p' :
00921         case 'P' : // PAWS1, PAWS2, PAWS3, Particle, or PETE Group
00922           if (strncasecmp(str, "paws1", 5) == 0) {
00923             // PAWS1 enabled    
00924             RtsLayer::enableProfileGroup(TAU_PAWS1); 
00925           } 
00926           else if (strncasecmp(str, "paws2", 5) == 0) {
00927             // PAWS2 enabled 
00928             RtsLayer::enableProfileGroup(TAU_PAWS2); 
00929           } 
00930           else if (strncasecmp(str, "paws3", 5) == 0) {
00931             // PAWS3 enabled 
00932             RtsLayer::enableProfileGroup(TAU_PAWS3); 
00933           } 
00934           else if (strncasecmp(str, "pa", 2) == 0) {
00935             // Particle enabled 
00936             RtsLayer::enableProfileGroup(TAU_PARTICLE);
00937           } 
00938           else {
00939             // PETE Profile Group enabled 
00940             RtsLayer::enableProfileGroup(TAU_PETE);
00941           } 
00942           break;
00943         case 'r' : 
00944         case 'R' : // Region Group 
00945           RtsLayer::enableProfileGroup(TAU_REGION);
00946           break;
00947         case 's' :
00948         case 'S' : // SubField or Sparse Index Group
00949           if (strncasecmp(str, "su", 2) == 0) {
00950             // SubField enabled 
00951             RtsLayer::enableProfileGroup(TAU_SUBFIELD);
00952           } 
00953           else {
00954             // Sparse Index Group
00955             RtsLayer::enableProfileGroup(TAU_SPARSE);
00956           }
00957           break;
00958         case 'd' :
00959         case 'D' : // Descriptor or DomainMap Group
00960           if (strncasecmp(str, "de", 2) == 0) {
00961             // Descriptor Overhead profiling enabled
00962             RtsLayer::enableProfileGroup(TAU_DESCRIPTOR_OVERHEAD);
00963           }
00964           else {
00965             // DomainMap profiling enabled
00966              RtsLayer::enableProfileGroup(TAU_DOMAINMAP);
00967           }
00968           break;
00969         case 'u' :
00970         case 'U' : // User or Utility 
00971           if (strncasecmp(str,"ut", 2) == 0) { 
00972             // Utility profiling enabled
00973             RtsLayer::enableProfileGroup(TAU_UTILITY);
00974           }
00975           else {
00976             // default - for u is USER 
00977             RtsLayer::enableProfileGroup(TAU_USER);
00978           }
00979           break;
00980         case 'v' :
00981         case 'V' : // ACLVIS Group
00982           RtsLayer::enableProfileGroup(TAU_VIZ);
00983           break;
00984         case '1' : // User1
00985           RtsLayer::enableProfileGroup(TAU_USER1);
00986           break; 
00987         case '2' : // User2
00988           RtsLayer::enableProfileGroup(TAU_USER2);
00989           break;
00990         case '3' : // User3
00991           RtsLayer::enableProfileGroup(TAU_USER3);
00992           break; 
00993         case '4' : // User4
00994           RtsLayer::enableProfileGroup(TAU_USER4);
00995           break;
00996         default  :
00997           cout << prog << " : Invalid Profile Group " << str << endl;
00998           break; 
00999       } 
01000       if ( (str = end) != NULL ) *str++ = '+';
01001     }
01002   }
01003   else {
01004     enableProfileGroup(TAU_DEFAULT); // Enable everything 
01005   }
01006   return 1;
01007 }
01008 
01010 void RtsLayer::ProfileInit(int argc, char **argv)
01011 {
01012   int i;
01013 
01014   for (i=0; i<argc; i++) {
01015     if (strcmp(argv[i],"--profile") == 0) {
01016         // Enable the profile groups
01017         if ( (i + 1) < argc && argv[i+1][0] != '-' )  { // options follow
01018            RtsLayer::resetProfileGroup(); // set it to blank
01019            RtsLayer::setAndParseProfileGroups(argv[0], argv[i+1]);
01020         }
01021     }
01022   }
01023   return;
01024 }
01025 
01026 
01028 bool RtsLayer::isCtorDtor(const char *name)
01029 {
01030 
01031   // If the destructor a static object is called, it could have a null name
01032   // after main is over. Treat it like a Dtor and return true.
01033   if (name[0] == 0) {
01034     DEBUGPROFMSG("isCtorDtor name is NULL" << endl;);
01035     return true; 
01036   }
01037   DEBUGPROFMSG("RtsLayer::isCtorDtor("<< name <<")" <<endl;);
01038   if (strchr(name,'~') == NULL) // a destructor 
01039     if (strchr(name,':') == NULL) // could be a constructor 
01040       return false;
01041     else  
01042       return true;
01043   else  
01044     return true;
01045 }
01046 
01048 // PrimaryGroup returns the first group that the function belongs to.
01049 // This is needed in tracing as Vampir can handle only one group per
01050 // function. PrimaryGroup("TAU_FIELD | TAU_USER") should return "TAU_FIELD"
01052 string RtsLayer::PrimaryGroup(const char *ProfileGroupName) 
01053 {
01054   string groups = ProfileGroupName;
01055   string primary; 
01056   string separators = " |"; 
01057   int start, stop, n;
01058 
01059   start = groups.find_first_not_of(separators);
01060   n = groups.length();
01061   stop = groups.find_first_of(separators, start); 
01062 
01063   if ((stop < 0) || (stop > n)) stop = n;
01064 
01065   primary = groups.substr(start, stop - start) ;
01066   return primary;
01067 
01068 }
01069 
01071 // TraceSendMsg traces the message send
01073 void RtsLayer::TraceSendMsg(int type, int destination, int length)
01074 {
01075 #ifdef TRACING_ON 
01076   long int parameter, othernode;
01077 
01078   if (RtsLayer::isEnabled(TAU_MESSAGE))
01079   {
01080     parameter = 0L;
01081     /* for send, othernode is receiver or destination */
01082     othernode = (long int) destination;
01083     /* Format for parameter is
01084        31 ..... 24 23 ......16 15..............0
01085           other       type          length       
01086      */
01087   
01088     parameter = (length & 0x0000FFFF) | ((type & 0x000000FF)  << 16) | 
01089               (othernode << 24);
01090     pcxx_Event(TAU_MESSAGE_SEND, parameter); 
01091 #ifdef DEBUG_PROF
01092     printf("Node %d TraceSendMsg, type %x dest %x len %x par %lx \n", 
01093         RtsLayer::myNode(), type, destination, length, parameter);
01094 #endif //DEBUG_PROF
01095   } 
01096 #endif //TRACING_ON
01097 }
01098 
01099   
01101 // TraceRecvMsg traces the message recv
01103 void RtsLayer::TraceRecvMsg(int type, int source, int length)
01104 {
01105 #ifdef TRACING_ON
01106   long int parameter, othernode;
01107 
01108   if (RtsLayer::isEnabled(TAU_MESSAGE)) 
01109   {
01110     parameter = 0L;
01111     /* for recv, othernode is sender or source*/
01112     othernode = (long int) source;
01113     /* Format for parameter is
01114        31 ..... 24 23 ......16 15..............0
01115           other       type          length       
01116      */
01117   
01118     parameter = (length & 0x0000FFFF) | ((type & 0x000000FF)  << 16) | 
01119               (othernode << 24);
01120     pcxx_Event(TAU_MESSAGE_RECV, parameter); 
01121   
01122 #ifdef DEBUG_PROF
01123     printf("Node %d TraceRecvMsg, type %x src %x len %x par %lx \n", 
01124         RtsLayer::myNode(), type, source, length, parameter);
01125 #endif //DEBUG_PROF
01126   }
01127 #endif //TRACING_ON
01128 }
01129 
01131 // DumpEDF() writes the function information in the edf.<node> file
01132 // The function info consists of functionId, group, name, type, parameters
01134 int RtsLayer::DumpEDF(void)
01135 {
01136 #ifdef TRACING_ON 
01137         vector<FunctionInfo*>::iterator it;
01138         char filename[1024], errormsg[1024];
01139         char *dirname;
01140         FILE* fp;
01141         int  numEvents, numExtra;
01142 
01143 
01144         if ((dirname = getenv("TRACEDIR")) == NULL) {
01145         // Use default directory name .
01146            dirname  = new char[8];
01147            strcpy (dirname,".");
01148         }
01149 
01150         sprintf(filename,"%s/events.%d.edf",dirname, RtsLayer::myNode());
01151         DEBUGPROFMSG("Creating " << filename << endl;);
01152         if ((fp = fopen (filename, "w+")) == NULL) {
01153                 sprintf(errormsg,"Error: Could not create %s",filename);
01154                 perror(errormsg);
01155                 return 0;
01156         }
01157         
01158         // Data Format 
01159         // <no.> events
01160         // # or \n ignored
01161         // %s %s %d "%s %s" %s 
01162         // id group tag "name type" parameters
01163 
01164         numExtra = 9; // Number of extra events
01165         numEvents = FunctionInfo::FunctionDB[RtsLayer::myThread()].size();
01166 
01167         numEvents += numExtra;
01168 
01169         fprintf(fp,"%d dynamic_trace_events\n", numEvents);
01170 
01171         fprintf(fp,"# FunctionId Group Tag \"Name Type\" Parameters\n");
01172 
01173         for (it = FunctionInfo::FunctionDB[RtsLayer::myThread()].begin(); 
01174           it != FunctionInfo::FunctionDB[RtsLayer::myThread()].end(); it++)
01175         {
01176           DEBUGPROFMSG("Node: "<< RtsLayer::myNode() <<  " Dumping EDF Id : " 
01177             << (*it)->GetFunctionId() << " " << (*it)->GetPrimaryGroup() 
01178             << " 0 " << (*it)->GetName() << " " << (*it)->GetType() 
01179             << " EntryExit" << endl;); 
01180         
01181           fprintf(fp, "%ld %s 0 \"%s %s\" EntryExit\n", (*it)->GetFunctionId(),
01182             (*it)->GetPrimaryGroup(), (*it)->GetName(), (*it)->GetType() );
01183         }
01184         // Now add the nine extra events 
01185         fprintf(fp,"%ld TRACER 0 \"EV_INIT\" none\n", (long) PCXX_EV_INIT); 
01186         fprintf(fp,"%ld TRACER 0 \"FLUSH_ENTER\" none\n", (long) PCXX_EV_FLUSH_ENTER); 
01187         fprintf(fp,"%ld TRACER 0 \"FLUSH_EXIT\" none\n", (long) PCXX_EV_FLUSH_EXIT); 
01188         fprintf(fp,"%ld TRACER 0 \"FLUSH_CLOSE\" none\n", (long) PCXX_EV_CLOSE); 
01189         fprintf(fp,"%ld TRACER 0 \"FLUSH_INITM\" none\n", (long) PCXX_EV_INITM); 
01190         fprintf(fp,"%ld TRACER 0 \"WALL_CLOCK\" none\n", (long) PCXX_EV_WALL_CLOCK); 
01191         fprintf(fp,"%ld TRACER 0 \"CONT_EVENT\" none\n", (long) PCXX_EV_CONT_EVENT); 
01192         fprintf(fp,"%ld TAU_MESSAGE -7 \"MESSAGE_SEND\" par\n", (long) TAU_MESSAGE_SEND); 
01193         fprintf(fp,"%ld TAU_MESSAGE -8 \"MESSAGE_RECV\" par\n", (long) TAU_MESSAGE_RECV); 
01194 
01195   
01196         fclose(fp);
01197 #endif //TRACING_ON
01198         return 1;
01199 }
01200 
01201 
01202 /***************************************************************************
01203  * $RCSfile: Profiler.cpp,v $   $Author: adelmann $
01204  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:32 $
01205  * IPPL_VERSION_ID: $Id: Profiler.cpp,v 1.1.1.1 2003/01/23 07:40:32 adelmann Exp $ 
01206  ***************************************************************************/
01207 
01208         
01209 

Generated on Mon Jan 16 13:23:55 2006 for IPPL by  doxygen 1.4.6