src/Profile/hpcxx/HPCxx_ProfileImpl.C

Go to the documentation of this file.
00001 //##########################################################################
00002 // HPC++Lib: An object-oriented class library for high performance
00003 //           parallel programming.
00004 //
00005 // Copyright (c) 1997
00006 //      Indiana University
00007 //      Los Alamos National Laboratory
00008 //      University of Oregon
00009 //
00010 // http://www.cs.uoregon.edu/paracomp/tau
00011 // http://www.acl.lanl.gov/Tulip
00012 // http://www.extreme.indiana.edu/HPC++
00013 //
00014 // Sameer Shende, Aida Chouchane
00015 // Pete Beckman, Dennis Gannon, Todd Green, Liz Johnson
00016 //
00017 // HPC++_VER:
00018 // Changes : Need to remove parentFunctionId and start time from pFuncList
00019 // and put it on a stack.
00020 //##########################################################################
00021 
00022 /********************************************************************/
00023 /*     New Version of the Profiler class                            */
00024 /* (compared to the profiler class defined for pC++)                */
00025 /*     Profiling of hpc++lib-based programs                         */
00026 /* February 1997 --  Aida Chouchane                                 */
00027 /********************************************************************/
00028 /* Description : hpc++ (lib) Profiler library  */
00029 
00030 
00031 #ifdef PROFILING_ON
00032 #       include <HPCxx_ProfileImpl.h>
00033 #       include <vector.h>
00034 
00035 /********************************************************
00036                   GLOBAL VARIABLES 
00037  *********************************************************/
00038 
00039 #define MAX_THREADS 1024
00040 /*function profiling*/
00041         int HPCXX_current_node;  /* node id */
00042         int HPCXX_current_context; /* context id */
00043 
00044         //map< int, HPCxx_ThProfiler, less<int> > thInfo; /* Thread info */ 
00045         // since index is tid 0..n-1 now, we can have a vector instead of map.
00046         //vector<HPCxx_ThProfiler> thInfo;
00047         HPCxx_ThProfiler thInfo[MAX_THREADS]; // instead of an STL map
00048 
00049         int HPCXX_threads; /*total number of created threads*/
00050         int HPCXX_exited_threads;/*total number of exited threads*/
00051 
00052 /*control to access threads and HPCXX_exited_threads variables*/
00053         nexus_mutex_t HPCXX_counter_mutex; 
00054         nexus_cond_t HPCXX_counter_cond;
00055 
00056         nexus_mutex_t HPCXX_thinfo_mutex; 
00057         nexus_mutex_t HPCXX_numfunc_mutex; 
00058 /* mutex to access no of functions in the context */
00059       int HPCXX_numfunc; 
00060 /*number of functions, considered for all threads created inside this context*/
00061 
00062 /* object-specific events*/
00063         nexus_mutex_t HPCXX_profile_event_mutex;
00064         int HPCXX_no_of_profile_events = 0 ;
00065 /* no. of events defined in the system - libraries etc. - margin */
00066         int HPCXX_ProfileSysEventMargin = 0;
00067 /* a mapping of event ids to event names */
00068         char * HPCXX_profile_event_table[HPCXX_MAX_PROFILE_EVENTS];
00069         map< int, int, less<int> > tidMap; 
00070 /* Thread id mapping from nex to real thread id  */ 
00071 
00072 /*********************************************************
00073                   GLOBAL FUNCTIONS
00074 
00075 **********************************************************/
00076 /* add only what you need */
00077 
00078 int tid() {
00079 //If tid returns the thread id as in 0..n-1 then we could just use an array
00080 // or vector for thInfo. A map would be necessary for tid() to translate
00081 // nexus tid to tid.
00082 // return (int) nexus_thread_self();
00083   int thread_id;
00084   thread_id = tidMap[nexus_thread_self()];
00085 #ifdef DEBUG_PROF
00086   cout << "tid returns " << thread_id <<endl;
00087 #endif
00088   return thread_id; //now it returns 0..n-1.
00089 }
00090 
00091 
00092 // Set and get the current node and context ids 
00093 void hpcxx_ProfileSetCurrentNodeId(const int& nid) {
00094   HPCXX_current_node = nid;
00095 }
00096 
00097 void hpcxx_ProfileSetCurrentContextId(const int& cid) {
00098   HPCXX_current_context = cid;
00099 }
00100 
00101 int hpcxx_ProfileThisNode() { 
00102   return HPCXX_current_node; 
00103 }
00104 
00105 int hpcxx_ProfileThisContext() {
00106   return HPCXX_current_context; 
00107 }
00108 
00109 
00110 void hpcxx_ProfileSetNumberOfFunc(const int& nr ) {
00111 // Does just what it says - sets HPCXX_numfunc to nr so other threads can
00112 // access it
00113   nexus_mutex_lock(&HPCXX_numfunc_mutex);
00114   HPCXX_numfunc = nr;
00115   nexus_mutex_unlock(&HPCXX_numfunc_mutex);
00116  
00117   return;
00118 }
00119 
00120 void hpcxx_ProfileInit(HPCxx_Group *g) {
00121 
00122   hpcxx_ProfileObjectInit();
00123   hpcxx_ProfileDumpObjectEventNames();  
00124 
00125   return;
00126 }
00127 
00128 void hpcxx_ProfileThreadInit(HPCxx_Group *g) {
00129 
00130   HPCxx_ThProfiler *master_profiler; // used in other func using "this"
00131 
00132   // init mutexes
00133   nexus_cond_init(&HPCXX_counter_cond, NULL);
00134   nexus_mutex_init(&HPCXX_counter_mutex, NULL);
00135   nexus_mutex_init(&HPCXX_numfunc_mutex, NULL);
00136   nexus_mutex_init(&HPCXX_profile_event_mutex, NULL);
00137 
00138   nexus_mutex_init(&HPCXX_thinfo_mutex, NULL);
00139   nexus_mutex_lock(&HPCXX_counter_mutex);
00140   HPCXX_threads = 0;
00141   HPCXX_exited_threads = 0;
00142   nexus_mutex_unlock(&HPCXX_counter_mutex);
00143 
00144   // create a new ThProfiler object
00145   const char* p = "parent";
00146   master_profiler =  new HPCxx_ThProfiler(p);
00147   // this increments no of threads and adds the entry to thInfo too.
00148 }
00149 
00150 int hpcxx_ProfileIsFunctionTopLevel(const int & thread_id, const int & function_id)
00151 {
00152 // Now, we have a stack, all we have to do is see if this is the only item 
00153 // on the stack and if its id matches.
00154 
00155   hpcxx_CurrentFuncInfo cf;
00156 
00157   cf = thInfo[thread_id].funcStack.top();
00158 
00159 #ifdef DEBUG_PROFILE 
00160   cout << "IsFunctionTopLevel : top returns cf with id "<< cf.myId << " parent = "<< cf.parentFunction << " start " << cf.start << endl;
00161 #endif /* DEBUG_PROFILE */
00162 
00163   if ((thInfo[thread_id].funcStack.size() == 1) && (cf.myId == function_id))
00164   { 
00165 #ifdef DEBUG_PROF
00166     cout << "IsFunctionTopLevel: size of stack == 1, myId matches  this is top level" << endl;
00167 #endif /* DEBUG_PROF */
00168     return 1;
00169   }
00170   else
00171     return 0;
00172 }
00173 
00174 void hpcxx_ProfileWaitChildren() {
00175 /* Parent thread (or distinguished thread in a context should not exit before
00176 the children - otherwise the children get killed */
00177   nexus_mutex_lock(&HPCXX_counter_mutex);
00178   while ((HPCXX_threads -1) != (HPCXX_exited_threads)) {
00179     nexus_cond_wait(&HPCXX_counter_cond, &HPCXX_counter_mutex);
00180   }
00181   nexus_mutex_unlock(&HPCXX_counter_mutex);
00182 #ifdef DEBUG_PROF
00183   cout << "Wait Children - unlocking..." << endl;
00184 #endif
00185 }
00186 
00187 
00188 void hpcxx_ProfileDecrChildren() {
00189 
00190   nexus_mutex_lock(&HPCXX_counter_mutex);
00191   HPCXX_exited_threads++;
00192 
00193 #ifdef DEBUG_PROF
00194   cout << "DecrChildren:exited threads " << HPCXX_exited_threads << " total threads " << HPCXX_threads << endl;
00195 #endif
00196 
00197   if (HPCXX_exited_threads == (HPCXX_threads-1) ) {
00198     //    cout << "signal condition" << endl;
00199     nexus_cond_signal(&HPCXX_counter_cond);
00200   } 
00201 
00202   // in either case, unlock the mutex 
00203   nexus_mutex_unlock(&HPCXX_counter_mutex);
00204  
00205 #ifdef DEBUG_PROF
00206     cout << "HPCXX_exited_threads successfully incremented..." << endl;
00207 #endif
00208 }
00209 
00210 void hpcxx_ProfileExit() {
00211 
00212 // This is called by hpcxx_exit() - thread 0
00213   hpcxx_ProfileExitThread();
00214 // Note for currentFunc to flow properly into IsFunctionTopLevel(), 
00215 // we MUST NEVER instrument either 
00216 // hpcxx_exit or hpcxx_ProfileExit or hpcxx_ProfileExitThread() routines.
00217   if (tid() == 0) { // master thread 0
00218     hpcxx_ProfileWaitChildren();
00219   } 
00220   else {
00221     hpcxx_ProfileDecrChildren();
00222   } 
00223 
00224 
00225   return;
00226 }
00227 
00228 void  hpcxx_ProfileExitThread( ){
00229 // Called by exit routine for threads 1..n-1.
00230 int my_tid = tid();
00231 int ident_ = thInfo[my_tid].currentFunc;
00232 double start_, duration ;  // typically done in ~HPCxx_FuncProfiler()
00233 hpcxx_CurrentFuncInfo cf; 
00234 int top_level_ = 0;
00235 
00236   /* Algo  with stack  : While size of stack != 0, do  what the destructor 
00237      would do */
00238     
00239   while (!thInfo[my_tid].funcStack.empty()) { // while stack is not empty
00240 
00241 #ifdef DEBUG_PROF 
00242   cout << "hpcxx_ProfileExitThread() : tid " << my_tid << " ident_ " << ident_ << endl; 
00243 #endif /* DEBUG_PROF */
00244 
00245     // do what the dtor of FuncProfiler does 
00246     thInfo[my_tid].incrFunctionCalls(ident_);   
00247 
00248     // get the start time;
00249     cf = thInfo[my_tid].funcStack.top(); // get the top record  
00250     start_ = cf.start; 
00251 
00252     if (start_ != 0.0) { //if "count only" is used, we put start as 0.0 
00253     //timing data 
00254       duration = pcxx_GetUSecD() - start_;
00255       thInfo[my_tid].setFunctionTime(ident_, duration);
00256     }
00257 
00258     top_level_ = hpcxx_ProfileIsFunctionTopLevel(my_tid, ident_);
00259 
00260     thInfo[my_tid].exitFunctionProfiling(duration);
00261     ident_ = thInfo[my_tid].currentFunc;
00262 
00263     if (top_level_) { // if I'm top level
00264       thInfo[my_tid].dumpInformationProfiling(); // dump all data to disk 
00265     } 
00266   } // while (!funcstack.empty)
00267   return;
00268     
00269 }
00270 
00271 int  hpcxx_ProfileGetAndIncrNoThreads() {
00272 // returns thread id and *then* increments the no of threads.
00273   nexus_mutex_lock(&HPCXX_counter_mutex); 
00274   int res = HPCXX_threads;
00275   HPCXX_threads ++;
00276   if (HPCXX_threads > MAX_THREADS) {
00277     cout << " ERROR: Increase size of MAX_THREADS, HPCXX_threads = " << HPCXX_threads << endl;
00278   }
00279   nexus_mutex_unlock(&HPCXX_counter_mutex);
00280 #ifdef DEBUG_PROF
00281   cout << "hpcxx_ProfileGetAndIncrNoThreads returns " << res << endl;
00282 #endif
00283   return res;
00284 }
00285 
00286 void hpcxx_ProfileCollNames(char *container, char *datatype, char *var_name, void *var_addr) {
00287   thInfo[tid()].collNames( container, datatype, var_name, var_addr);
00288 }
00289 void hpcxx_ProfileCollAttr(void *var_addr, int no_of_elements,
00290                              int dimension, int size_of_aggregate)  {
00291   thInfo[tid()].collAttr( var_addr,no_of_elements,dimension, size_of_aggregate);
00292 
00293 }
00294 void hpcxx_ProfileIncrementCounter(void *addr,int counter_id) {
00295 /* increment a counter associated with an object whose address is addr */
00296   thInfo[tid()].incrementAggregateCounter( addr, counter_id);
00297 }
00298 
00299 int hpcxx_ProfileRegisterEvent(int eventid, char *event_name) { 
00300  nexus_mutex_init(&HPCXX_profile_event_mutex, NULL);
00301   
00302   /* In the table profile_event_table, add the event name and id */
00303     if ((eventid < 0) || (eventid > HPCXX_MAX_PROFILE_EVENTS ))
00304     {
00305         printf("Error in hpcxx_ProfileRegisterEvent : event id %d %s illegal", eventid, event_name);
00306         return -1;
00307     }
00308 
00309 #ifdef DEBUG_PROF
00310     cout << "HPCXX_no_of_profile_events = " << HPCXX_no_of_profile_events << endl;
00311 #endif
00312     /*if user event, convert to the actual event-id in the event-table*/
00313     //if (HPCXX_ProfileUserEventMargin != -1)
00314      //eventid = eventid + HPCXX_ProfileUserEventMargin;
00315     //if (HPCXX_ProfileSysEvents!= -1)
00316 #ifdef DEBUG_PROF
00317     cout << "HPCXX_ProfileSysEventMargin = " << HPCXX_ProfileSysEventMargin <<endl; 
00318 #endif
00319       eventid = eventid + HPCXX_ProfileSysEventMargin;
00320       //else
00321       //HPCXX_ProfileUserEventMargin ++;
00322 
00323     //    cout << "event to add "  << eventid << endl;
00324     /*Safety check: register event only if it hasn't already 
00325       been register by some other thread*/
00326 
00327 #ifdef DEBUG_PROF
00328       cout << "HPCXX_profile_event_table[" << eventid << "] == NULL:: " <<  (HPCXX_profile_event_table[eventid] == NULL) << endl;
00329 #endif
00330     if ( HPCXX_profile_event_table[eventid] == NULL) {
00331       HPCXX_profile_event_table[eventid] = strnew(event_name);
00332 
00333       nexus_mutex_lock(&HPCXX_profile_event_mutex);
00334       HPCXX_no_of_profile_events ++;
00335       nexus_mutex_unlock(&HPCXX_profile_event_mutex);                
00336     }
00337   return 1;
00338 }
00339 
00340 int hpcxx_ProfileGetEventCounter(void)
00341 {
00342   int res;
00343   nexus_mutex_lock(&HPCXX_profile_event_mutex);
00344   res = HPCXX_no_of_profile_events;
00345   nexus_mutex_unlock(&HPCXX_profile_event_mutex);
00346   return res;
00347 }
00348 
00349 int hpcxx_ProfileShowEventTable(void)
00350 { /* for debugging */
00351     int i;
00352 
00353     nexus_mutex_lock(&HPCXX_profile_event_mutex);
00354     for (i = 0; i < HPCXX_no_of_profile_events; i++)
00355     {
00356         printf("show_profile_event_table: Event id %d event =%s \n",i, HPCXX_profile_event_table[i]);
00357     }
00358     nexus_mutex_unlock(&HPCXX_profile_event_mutex);
00359     return 1;
00360 }
00361 
00362 int hpcxx_ProfileObjectInit(void)
00363 {
00364 
00365   HPCXX_ProfileSysEventMargin =  HPCXX_no_of_profile_events ;
00366 
00367   //   hpcxx_ProfileInitNrOfSysEvents();
00368 /* During startup, on node 0, register the profiling events */
00369 
00370    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Wait_HPCxx_Cond          ,"cond_wait");
00371    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Signal_HPCxx_Cond    ,"cond_signal");
00372    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Broadcast_HPCxx_Cond ,"cond_broadcast");
00373    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Read_HPCxx_GlobalPtr ,"global_ptr_read");
00374    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Write_HPCxx_GlobalPtr ,"global_ptr_write");
00375    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Write_HPCxx_SyncQ,"sync_q_write");
00376    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Read_HPCxx_SyncQ ,"sync_q_read");
00377    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_WaitAndCopy_HPCxx_SyncQ,
00378                               "sync_q_wait_and_copy");
00379    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Create_HPCxx_Thread,
00380                               "thread_create");
00381    /*   hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Stop_HPCxx_Thread,"thread_stop");
00382         hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Yield_HPCxx_Thread,"thread_yield");
00383         hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Sleep_HPCxx_Thread,"thread_sleep");
00384    */
00385    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Suspend_HPCxx_Thread,
00386                               "thread_suspend");
00387    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Resume_HPCxx_Thread,
00388                               "thread_resume");
00389    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Join_HPCxx_Thread,"thread_join");
00390    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Wait_HPCxx_CSem,"csem_wait");
00391    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Increment_HPCxx_CSem,"csem_incr");
00392    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Read_HPCxx_Sync,"sync_read");
00393    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Write_HPCxx_Sync,"sync_write");
00394    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Lock_HPCxx_Mutex,"mutex_lock");
00395    hpcxx_ProfileRegisterEvent(HPCXX_PROFILE_Unlock_HPCxx_Mutex,"mutex_unlock");
00396 
00397 #ifdef DEBUG_PROF
00398    hpcxx_ProfileShowEventTable();
00399 #endif
00400    return 1;
00401 }
00402 
00403 /*  void hpcxx_ProfileInitNrOfSysEvents() {
00404     if (HPCXX_ProfileUserEventMargin == 0)
00405     HPCXX_ProfileSysEvents = 0;
00406     else
00407     HPCXX_ProfileSysEvents = HPCXX_ProfileUserEventMargin - 1;
00408     }*/
00409 
00410 int  hpcxx_ProfileDumpObjectEventNames()
00411 {
00412   /* dump in profile.ctab object profile event id and its name */
00413   int  out, nevents,i;
00414   char buf[256];
00415   char profname[16];
00416         
00417   sprintf (profname, "profile.ctab");
00418   if ( (out = creat (profname, 0644)) == -1 ) {
00419   perror (profname);
00420   exit (1);
00421   }
00422         
00423   nevents = hpcxx_ProfileGetEventCounter();
00424   sprintf(buf,"%d\n", nevents);
00425   write(out, buf,strlen(buf));
00426 
00427   for(i = 0; i < nevents; i++)
00428   { 
00429     sprintf(buf,"%d \"%s\"\n",i, HPCXX_profile_event_table[i]);
00430     write(out, buf, strlen(buf));
00431   }
00432   close(out);
00433   return 1;
00434 }
00435 
00436 
00437 // HPCxx_ProfileVarInfo member functions
00438 
00439 HPCxx_ProfileVarInfo:: HPCxx_ProfileVarInfo() 
00440 { 
00441   for(int i = 0; i< HPCXX_MAX_COUNTERS; i++) {
00442     nexus_mutex_init(&counterLocks[i], NULL);
00443     nexus_mutex_lock(&counterLocks[i]);
00444     counters[i] = 0;
00445     nexus_mutex_unlock(&counterLocks[i]);
00446   }
00447   numelems = size = 0;
00448   dim = 1; /* defaults */
00449 }
00450 
00451 HPCxx_ProfileVarInfo:: HPCxx_ProfileVarInfo(const char *cname, const char *ctype, const char *vname)
00452 { 
00453   containerName = strnew(cname);
00454   containerType = strnew(ctype);
00455   varName = strnew(vname);
00456   for(int i = 0; i< HPCXX_MAX_COUNTERS; i++) {
00457     nexus_mutex_init(&counterLocks[i], NULL);
00458           nexus_mutex_lock(&counterLocks[i]);
00459           counters[i] = 0;
00460           nexus_mutex_unlock(&counterLocks[i]);
00461   }
00462   numelems = size = 0;
00463   dim = 1; /* defaults */
00464 }
00465 
00466 void HPCxx_ProfileVarInfo:: incrementCounter(int counter_id)
00467 {
00468   if((counter_id > HPCXX_MAX_COUNTERS) || (counter_id < 0))
00469     {
00470       cerr << "Range error counter id = " << counter_id << endl;        
00471     }   
00472   else {
00473     nexus_mutex_lock(&counterLocks[counter_id]);
00474     counters[counter_id] ++;
00475     nexus_mutex_unlock(&counterLocks[counter_id]);
00476   }
00477 }
00478 
00479 void HPCxx_ProfileVarInfo:: registerAttributes(int no_of_elements, int dimension, int size_of_aggregate)
00480 {
00481         numelems = no_of_elements;
00482         dim = dimension;
00483         size = size_of_aggregate;
00484 
00485         return;
00486 }
00487 
00488 const  HPCxx_ProfileVarInfo& HPCxx_ProfileVarInfo:: operator = ( const HPCxx_ProfileVarInfo& t) {
00489   containerName = t.containerName;
00490   containerType = t.containerType;
00491   varName = t.varName;
00492   numelems = t.numelems;
00493   dim = t.dim;
00494   size = t.size;
00495   return *this;
00496 }
00497 
00498 
00499 // ThProfiler member function definitions 
00500 HPCxx_ThProfiler:: HPCxx_ThProfiler(int pid ){
00501   id_ = hpcxx_ProfileGetAndIncrNoThreads();
00502   // id_ and nexus_tid mapping is preserved in tidMap
00503   tidMap[nexus_thread_self()] = id_;
00504   parentTh_ = pid ;
00505   contNameDb_ = new map<void*, HPCxx_ProfileVarInfo, lptr>();
00506   currentFunc = -1; // Do not remove. Used later to set parent = -1 in 
00507                     // updateFunctions
00508   
00509   nexus_mutex_lock(&HPCXX_thinfo_mutex);
00510   thInfo[tid()] = *this;  // add ThProfiler to the thInfo map  
00511   nexus_mutex_unlock(&HPCXX_thinfo_mutex);
00512 }
00513 
00514 HPCxx_ThProfiler:: HPCxx_ThProfiler(const char* p  ){
00515   id_ = hpcxx_ProfileGetAndIncrNoThreads();
00516   // id_ and nexus_tid mapping is preserved in tidMap
00517   tidMap[nexus_thread_self()] = id_;
00518   parentTh_ = -1;
00519   contNameDb_ = new map<void*, HPCxx_ProfileVarInfo, lptr>();
00520   currentFunc = -1; // Do not remove. Used later to set parent = -1 in 
00521                     // updateFunctions
00522 
00523   nexus_mutex_lock(&HPCXX_numfunc_mutex);
00524   thInfo[tid()] = *this;
00525   nexus_mutex_unlock(&HPCXX_numfunc_mutex);
00526 }
00527 
00528 void HPCxx_ThProfiler:: initFunctionList(const int& n) {
00529 // n is the number of functions registered in this context
00530   pFuncList_ = new hpcxx_ProfileFuncDescr [n];
00531 
00532   for (int i = 0 ; i < n ; (i)++)
00533     {
00534       pFuncList_[i].numcalls = 0;
00535       pFuncList_[i].usec = 0.0;
00536       pFuncList_[i].cumusec = 0.0;
00537     }
00538 }
00539 
00540 const  HPCxx_ThProfiler& HPCxx_ThProfiler:: operator = ( const HPCxx_ThProfiler& t) {
00541   id_ = t.id_;
00542   pFuncList_ = t.pFuncList_;
00543   currentFunc = t.currentFunc;
00544   parentTh_ = t.parentTh_ ;
00545   contNameDb_ = t.contNameDb_;
00546   return *this;
00547 }
00548 
00549 int HPCxx_ThProfiler:: getNumberOfCollections() {
00550   return contNameDb_->size();
00551 }
00552 
00553 void HPCxx_ThProfiler:: incrFunctionCalls(const int& fid) {
00554   // checkFunctionList_();   // is it needed? 
00555   pFuncList_[fid].numcalls++;
00556 #ifdef DEBUG_PROF
00557   cout << "incrFunctionCalls: tid = "<< id_ << " fid = " << fid << " numcalls = "<< pFuncList_[fid].numcalls << endl;
00558 #endif /* DEBUG_PROF */
00559 }
00560 
00561 void HPCxx_ThProfiler:: setFunctionTime(const int& fid , const double& duration) {
00562   // set cumulative inclusive (cumusec) and exclusive (usec) fields
00563   pFuncList_[fid].usec += duration;
00564   pFuncList_[fid].cumusec += duration;
00565 #ifdef DEBUG_PROF
00566   cout << "setFunctionTime: tid = "<< id_ << " pFuncList_["<< fid << "].usec = "<< pFuncList_[fid].usec << "cumusec = " << pFuncList_[fid].cumusec << endl; 
00567 #endif /* DEBUG_PROF */
00568 }
00569 
00570 void HPCxx_ThProfiler:: updateFunctions(const int&  fct_id, const double& start) {
00571   // set function ids for parent and current function and flag it as active
00572   // parentFunc_ = currentFunc;
00573   hpcxx_CurrentFuncInfo cf;
00574   cf.parentFunction = currentFunc;
00575   cf.myId = fct_id;
00576   cf.start = start; 
00577   // sets parentFunctionId to currentFunction, id to fct_id and the start time
00578   funcStack.push(cf);
00579 
00580   currentFunc = fct_id; 
00581 
00582 #ifdef DEBUG_PROF
00583   cout << "updateFunctions: tid = "<< id_ << " fid = "<< fct_id << " parent = " << cf.parentFunction << endl;
00584 #endif /* DEBUG_PROF */
00585 
00586 }
00587 
00588 void HPCxx_ThProfiler:: exitFunctionProfiling(const double& duration) {
00589   // Let exitFunctionProfiling do the "pop" on the stack
00590   hpcxx_CurrentFuncInfo cf;
00591   // While exiting, set the function as inactive
00592 
00593   cf = funcStack.top();
00594 #ifdef DEBUG_PROF 
00595   cout << "exitFunctionProfiling tid = "<< id_ << " cf.par = "<< cf.parentFunction << " cf.myId " << cf.myId << " duration = " << duration << endl;
00596 #endif /* DEBUG_PROF */
00597   funcStack.pop(); // This record removed from the stack
00598   currentFunc = cf.parentFunction; // sets it. 
00599  
00600 
00601   // decrement the time spent exclusively in the parent function
00602   if (duration > 1e6)  // double - if resolution is positive microsecs.
00603     pFuncList_[cf.parentFunction].usec -= duration;
00604 #ifdef DEBUG_PROF
00605   cout << "exitFunctionProfiling: tid = "<< id_ << " currentFunc = " << currentFunc  << endl;
00606 #endif  /* DEBUG_PROF */
00607 
00608 }
00609 
00610 void HPCxx_ThProfiler:: collNames(char *container, char *datatype, 
00611                                          char *var_name, void *var_addr) {
00612   (*contNameDb_)[var_addr] = HPCxx_ProfileVarInfo(container, datatype, var_name);
00613   /* register the name e.g., "distributed_vector", "int", "row", &row */
00614   
00615   /*   for(map<void*, HPCxx_ProfileVarInfo, lptr>::const_iterator it = contNameDb_->begin();
00616        it != contNameDb_->end();
00617        ++it) {}*/
00618 }
00619 
00620 void HPCxx_ThProfiler:: collAttr(void *var_addr, int no_of_elements, 
00621                                    int dimension, int size_of_aggregate) {
00622   map<void*, HPCxx_ProfileVarInfo, lptr>::iterator 
00623    it = contNameDb_->find(var_addr);
00624   if ( (it == contNameDb_->end()) && ((*it).first != var_addr) )
00625     return;
00626 
00627   (*contNameDb_)[var_addr].registerAttributes(no_of_elements, dimension, 
00628                                                 size_of_aggregate);
00629 /*   for(map<void*, HPCxx_ProfileVarInfo, lptr>::const_iterator itc = contNameDb_->begin();
00630       itc != contNameDb_->end();
00631       ++itc) {}*/  
00632 }
00633 
00634 void HPCxx_ThProfiler:: incrementAggregateCounter(void *addr,
00635                                                      int counter_id) {
00636   map<void*, HPCxx_ProfileVarInfo, lptr>::iterator 
00637     it = contNameDb_->find(addr);
00638   if (it == contNameDb_->end())
00639     return;
00640   (*contNameDb_)[addr].incrementCounter(counter_id);
00641 }  
00642 
00643 
00644 void HPCxx_ThProfiler:: setStartTime(const int & fid, const double & s) {
00645 /* old code - we may remove this function  */
00646 
00647 //  pFuncList_[fid].start = s;
00648 
00649 #ifdef DEBUG_PROF
00650  // cout << "setStartTime: tid = "<< id_ << " pFuncList_["<< fid << "].start = "<< pFuncList_[fid].start << endl; 
00651 #endif /* DEBUG_PROF */
00652 } 
00653 
00654 void HPCxx_ThProfiler:: dumpInformationProfiling() {
00655   int i;
00656   char buf[256];
00657   char* filename;
00658   int f;
00659 
00660   char counter_info[32];
00661   char counter_string[HPCXX_MAX_COUNTER_STRING]; 
00662   int numcoll;
00663   int no_active_counters;  
00664   
00665   nexus_mutex_lock(&HPCXX_numfunc_mutex);
00666   int n = HPCXX_numfunc;
00667   nexus_mutex_unlock(&HPCXX_numfunc_mutex);
00668 
00669   filename = new char [256];
00670   sprintf (filename, "profile.%d.%d.%d",hpcxx_ProfileThisNode(),
00671            hpcxx_ProfileThisContext(), id_ );  // id_ is the tid  
00672 
00673   if ( (f = creat (filename, 0644)) == -1 ) {
00674     cout << " Error in creating " << filename << " !!!!!!!!!!!!!!!!!!!!!!" << endl;
00675     perror (filename);
00676     exit (1);
00677   }
00678 
00679 #ifdef DEBUG_PROF
00680   cout << " before dumping function data " << endl; 
00681 #endif /* DEBUG_PROF */
00682   sprintf (buf, "%d func\n",n);
00683 
00684   write(f, buf, strlen(buf) );  
00685   // checkFunctionList_();
00686   // should we check?
00687 
00688   for (i = 0; i<n; i++) {
00689     if (pFuncList_[i].numcalls > 0 ) { // instead of usec > 0.0
00690       sprintf (buf, "%d %G %G\n", 
00691                pFuncList_[i].numcalls,
00692                pFuncList_[i].usec,
00693                pFuncList_[i].cumusec); 
00694       write(f, buf, strlen(buf) );
00695     }
00696     else {
00697       sprintf (buf, "%d 0 0 \n", 
00698                pFuncList_[i].numcalls); 
00699       write(f, buf, strlen(buf) );
00700     }
00701   }
00702 
00703 #ifdef DEBUG_PROF
00704   cout << " before dumping coll data " << endl; 
00705 #endif /* DEBUG_PROF */
00706   //numcoll = hpcxx_ProfileGetNumberOfCollection();
00707   numcoll = thInfo[id_].getNumberOfCollections(); 
00708   sprintf (buf, "%d aggregates\n", numcoll);
00709   write (f, buf, strlen(buf));
00710   if (numcoll > 0) { 
00711     for(map<void*, HPCxx_ProfileVarInfo, lptr>::const_iterator it = contNameDb_->begin();
00712         it != contNameDb_->end();
00713         ++it) 
00714       { 
00715         const map<void*, HPCxx_ProfileVarInfo, lptr>::value_type& elem = *it;
00716   
00717   #ifdef DEBUG_PROF
00718       cout << "printing into buffer" << endl;
00719   #endif
00720       sprintf(counter_string,""); /* NULL - clean it*/
00721       no_active_counters = 0; 
00722       for(i = 0; i < HPCXX_MAX_COUNTERS; i++)
00723         {               
00724         if(elem.second.counters[i] != 0)
00725           {
00726             no_active_counters ++;
00727             sprintf(counter_info,"%d %ld ", i, elem.second.counters[i]);
00728             /* note space after %ld (sp between nos) is imp */
00729             strcat(counter_string,counter_info);
00730   #ifdef DEBUG_PROF
00731             printf("thread %d: active %d, id %d no %d\n",
00732                    tid(), 
00733                    no_active_counters, i, elem.second.counters[i]);
00734   #endif /* DEBUG_PROF */
00735             
00736           }
00737         } /* now no_active_counters and counter_string can be used */
00738   #ifdef DEBUG_PROF
00739       printf("thread %d: string =%s\n",
00740            tid(), 
00741            counter_string);
00742   #endif /* DEBUG_PROF */
00743       
00744       
00745       sprintf(buf, "%d %d %d %d %s %s %s %s\n",
00746             no_active_counters,
00747             elem.second.numelems,
00748             elem.second.dim,
00749             elem.second.size,
00750             counter_string,
00751             elem.second.containerName,
00752             elem.second.containerType,
00753             elem.second.varName);
00754      
00755       write (f, buf, strlen(buf));
00756     }
00757   } // numcoll > 0
00758   close (f);
00759 }
00760 
00761 
00762 
00763 
00764 HPCxx_FuncProfiler:: HPCxx_FuncProfiler(int id){
00765 int my_tid = tid();
00766 #ifdef DEBUG_PROF
00767   printf("Inside HPCxx_FuncProfiler ctor 1 arg id  = %d, thread = %d\n",id, my_tid);
00768 #endif
00769   
00770   // function identifier
00771   ident_ = id;
00772 
00773   // no. of functions field initialized.
00774   // if nf_ is -1, then it stands for "count only" no timing data to be collected.
00775   nf_ = 0; // collect timing data
00776 
00777   start_ = pcxx_GetUSecD();
00778   thInfo[my_tid].updateFunctions(id, start_); 
00779   // no need to go thru' hpcxx_ProfileFuncEnter 
00780   // this sets parent function ids and active flag for id.
00781 
00782     
00783   // thInfo[my_tid].setStartTime(id, start_);
00784   // no need to go through hpcxx_ProfileSetStartTime(id, start_);
00785 
00786 }
00787 
00788 
00789 HPCxx_FuncProfiler:: HPCxx_FuncProfiler(int id, int num ) {
00790   int my_tid = tid();
00791 #ifdef DEBUG_PROF
00792   printf("Inside HPCxx_FuncProfiler ctor 2 arg id  = %d, num = %d, thread %d\n",id, num, my_tid);
00793 #endif
00794   ident_ = id;  
00795 
00796   nf_ = num;
00797 
00798   hpcxx_ProfileSetNumberOfFunc(num );
00799   //necessary for initializing the number of functions 
00800   //in other threads... same address space!
00801 
00802   thInfo[my_tid].initFunctionList(num) ;
00803   // init Function List creates pFuncList and initializes entries
00804 
00805   start_ = pcxx_GetUSecD();
00806   thInfo[my_tid].updateFunctions(id, start_); 
00807   // update Functions sets parent id, current id, and also sets id as "active"
00808 
00809   
00810   // thInfo[my_tid].setStartTime(id, start_);
00811   // instead of using hpcxx_ProfileSetThreadStartTime(start_);
00812 
00813 
00814 }
00815 
00816 HPCxx_FuncProfiler:: HPCxx_FuncProfiler(int id,char countonly){
00817  int my_tid = tid();
00818 #ifdef DEBUG_PROF
00819   printf("Inside countonly HPCxx_FuncProfiler ctor 2 arg id  = %d, countonly = %c, thread %d\n",id, countonly, my_tid);
00820 #endif
00821   ident_ = id;
00822 
00823   nf_ = -1; // count only
00824 
00825   thInfo[my_tid].updateFunctions(id, 0.0);
00826   // update Functions sets parent id, current id, and also sets id as "active"
00827 
00828   // In this ctor - no timing information is collected "count only"
00829 }
00830 
00831 HPCxx_FuncProfiler:: HPCxx_FuncProfiler(int id, int num , char countonly ) {
00832   int my_tid = tid();
00833 #ifdef DEBUG_PROF
00834   printf("Inside counonly HPCxx_FuncProfiler ctor 3 arg id  = %d, num = %d, thread %d\n",id, num, my_tid);
00835 #endif
00836   ident_ = id;  
00837 
00838   nf_ = -1; // count only  - nf_ == -1, start = 0.0
00839 
00840   hpcxx_ProfileSetNumberOfFunc(num );
00841   //necessary for initializing the number of functions 
00842   //in other threads... same address space!
00843 
00844   thInfo[my_tid].initFunctionList(num) ;
00845   // init Function List creates pFuncList and initializes entries
00846 
00847   thInfo[my_tid].updateFunctions(id, 0.0); 
00848   // update Functions sets parent id, current id, and also sets id as "active"
00849 
00850 }
00851 
00852 
00853 
00854 HPCxx_FuncProfiler:: ~HPCxx_FuncProfiler() {
00855    double duration = 0.0;
00856    int my_tid = tid();
00857 #ifdef DEBUG_PROF
00858    printf("DESCTRUCTOR HPCxx_FuncProfiler id = %d, thread = %d\n", ident_, my_tid );
00859 #endif
00860   
00861   thInfo[my_tid].incrFunctionCalls(ident_);   
00862      
00863   if (!hpcxx_ProfileIsFunctionTopLevel(my_tid, ident_)) {
00864     if (nf_ != -1) { // counts only is -1  then we don't need to incr time
00865       duration = pcxx_GetUSecD() - start_;
00866       thInfo[my_tid].setFunctionTime(ident_, duration);
00867     }
00868 
00869     thInfo[my_tid].exitFunctionProfiling(duration);
00870   } 
00871   // Top level functions are taken care of elsewhere
00872   // removed if (ident_ == 0) restriction here.  
00873 }
00874 
00875 
00876 #endif /* PROFILING_ON */
00877 

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