src/Utility/Timer.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  *
00022  * Visit http://people.web.psi.ch/adelmann/ for more details
00023  *
00024  ***************************************************************************/
00025 
00026 /***************************************************************************
00027  * DESCRIPTION:
00028  *      Timer.C constains the implementation of the class Timer which
00029  * provides a generic way to time things.  Each Timer keeps a cumulative
00030  * time.  It can be started, stopped, or cleared.
00031  *      On the HPs, the clock time is obtained by calls to the routine
00032  * gettimeofday() and the user, system, and total cpu times are obtained
00033  * using the routine times()
00034  *
00035  * This class was originally developed by Mark Nelson in the Theoretical
00036  * Biophysics Group at the University of Illinois.
00037  ***************************************************************************/
00038 
00039 // include files
00040 #include "Utility/Timer.h"
00041 #include "Profile/Profiler.h"
00042 
00043 #ifdef IPPL_XT3
00044 #include <catamount/dclock.h>
00045 #endif
00046 
00047 #if defined(IPPL_T3E)
00048 #define tick_secs(ticks, clock_ticks) \
00049 ( (double) ticks / (double) clock_ticks )          
00050 #endif
00051 
00052 //  TIMERON and TIMEROFF define the current state of a Timer
00053 #define TIMEROFF        0
00054 #define TIMERON         1
00055 
00056 /************************************************************************/
00057 /*                                                                      */
00058 /*                      FUNCTION Timer                                  */
00059 /*                                                                      */
00060 /*      This is the constructor for the class Timer.  It sets the timer */
00061 /*  status to TIMEROFF and clears all the values.  It also makes a call */
00062 /*  to sysconf to determine the number of clock ticks per second for    */
00063 /*  use with the call times()                                           */
00064 /*  It also makes calibration calls.                                    */
00065 /*                                                                      */
00066 /************************************************************************/
00067 
00068 Timer::Timer()
00069 {
00070   TAU_PROFILE("Timer::Timer()", "void ()", TAU_UTILITY );
00071 
00072 #ifdef __MWERKS__
00073   // For now, stub out all Timer guts for MetroWerks
00074 #else
00075 
00076 #ifndef IPPL_XT3
00077   cpu_speed = sysconf(_SC_CLK_TCK);
00078 #endif
00079   timer_state = TIMEROFF;
00080   clear();
00081 
00082   // Calibration:
00083 #if defined(IPPL_T3E)
00084   long start_time, end_time, total_time;
00085   (void) rtclock();
00086   start_time = rtclock();
00087   end_time = rtclock();
00088   total_time = end_time - start_time;
00089   calibration = tick_secs(total_time, cpu_speed);
00090 #else
00091   // No other machines have calibration defined yet.
00092   calibration = 0.0;
00093 #endif
00094 
00095 #endif // __MWERKS__
00096 }
00097 /*                      END OF FUNCTION Timer                           */
00098 
00099 Timer::~Timer()
00100 {
00101   TAU_PROFILE("Timer::~Timer()", "void ()", TAU_UTILITY );
00102 
00103 #ifdef __MWERKS__
00104   // For now, stub out all Timer guts for MetroWerks
00105 #else
00106 
00107   // Check to see if the timer is on
00108   if (timer_state == TIMERON)
00109     {
00110       //  Destroying a running Timer
00111       // ERRORMSG(level2 << "TRIED TO DELETE A RUNNING TIMER!\n");
00112       // ERRORMSG("STOPPING AND DELETING TIMER." << endl);
00113       timer_state=TIMEROFF;
00114     }
00115 
00116 #endif // __MWERKS__
00117 }
00118 
00119 /************************************************************************/
00120 /*                                                                      */
00121 /*                      FUNCTION clear                                  */
00122 /*                                                                      */
00123 /*      clear sets all of the accumulated times for this timer to 0.    */
00124 /*  It is intended to only be used on a stopped timer.  If it is used   */
00125 /*  on a running timer, a warning message is printed, the timer is      */
00126 /*  stopped and all of its values are cleared.                          */
00127 /*                                                                      */
00128 /************************************************************************/
00129 
00130 void Timer::clear()
00131 {
00132   TAU_PROFILE("Timer::clear()", "void ()", TAU_UTILITY );
00133 
00134 #ifdef __MWERKS__
00135   // For now, stub out all Timer guts for MetroWerks
00136   return;
00137 #else
00138   // Check to see if the timer if on
00139   if (timer_state == TIMERON)
00140     {
00141       //  Clearing a running Timer
00142       // ERRORMSG(level2 << "TRIED TO CLEAR A RUNNING TIMER!\n");
00143       // ERRORMSG("SETTING ALL VALUES TO 0 AND STOPPING TIMER." << endl);
00144       timer_state = TIMEROFF;
00145     }
00146 
00147   //  Set all of the accumulated values to 0
00148 #ifdef IPPL_XT3
00149   current_clock = 0.0;
00150 #else
00151   current_secs = 0;
00152   current_usecs = 0;
00153   current_user_time = 0;
00154   current_system_time = 0;
00155 #endif // IPPL_TFLOP
00156 
00157 #endif // __MWERKS__
00158 }
00159 /*                      END OF FUNCTION clear                           */
00160 
00161 /************************************************************************/
00162 /*                                                                      */
00163 /*                      FUNCTION start                                  */
00164 /*                                                                      */
00165 /*      start a Timer timing.  This will start adding time elapsed to   */
00166 /*  the current accumulated values of the timer.  If you try to start   */
00167 /*  a timer that is already running, a warning message is printed       */
00168 /*                                                                      */
00169 /************************************************************************/
00170 
00171 void Timer::start()
00172 {
00173   TAU_PROFILE("Timer::start()", "void ()", TAU_UTILITY );
00174 
00175 #ifdef __MWERKS__
00176   // For now, stub out all Timer guts for MetroWerks
00177   return;
00178 #else
00179   //  Check to see if the timer is already running
00180   if (timer_state == TIMERON)
00181     {
00182       // ERRORMSG(level2 << "TRIED TO START A RUNNING TIMER!\n");
00183       // ERRORMSG("CONTINUING UNCHANGED." << endl);
00184       return;
00185     }
00186 
00187   //  Get the current time values from the system
00188 #if defined(IPPL_T3E)
00189   last_secs = rtclock();
00190   // Omit non-real times on T3E:
00191   last_usecs = 0;
00192   last_user_time = 0;
00193   last_system_time = 0;
00194 #elif defined(IPPL_XT3)
00195   last_clock = dclock();
00196 #else
00197   gettimeofday(&tvbuf, &tzbuf);
00198   times(&tmsbuf);
00199   //  Set the starting values to the current time
00200   last_secs = tvbuf.tv_sec;
00201   last_usecs = tvbuf.tv_usec;
00202   last_user_time = tmsbuf.tms_utime;
00203   last_system_time = tmsbuf.tms_stime;
00204 #endif
00205 
00206   //  Set the state of the Timer
00207   timer_state = TIMERON;
00208   return;
00209 #endif // __MWERKS__
00210 }
00211 /*                      END OF FUNCTION start                           */
00212 
00213 /************************************************************************/
00214 /*                                                                      */
00215 /*                              FUNCITON stop                           */
00216 /*                                                                      */
00217 /*      stop stops a Timer from accumulating time.  If you try to stop */
00218 /*  a stopped Timer, a warning message is printed                       */
00219 /*                                                                      */
00220 /************************************************************************/
00221 
00222 void Timer::stop()
00223 {
00224   TAU_PROFILE("Timer::stop()", "void ()", TAU_UTILITY );
00225 
00226 #ifdef __MWERKS__
00227   // For now, stub out all Timer guts for MetroWerks
00228   return;
00229 #else
00230   //  Check to see if the timer is already stopped
00231   if (timer_state == TIMEROFF)
00232     {
00233       // ERRORMSG(level2 << "TRIED TO STOP A STOPPED TIMER!\n");
00234       // ERRORMSG("CONTINUING UNCHANGED." << endl);
00235       return;
00236     }
00237 
00238   //  Get the current time values from the system and accumulate
00239 #if defined(IPPL_T3E)
00240   long end_time = rtclock();
00241 
00242   current_secs +=  end_time - last_secs;
00243   current_usecs += 0;
00244   current_user_time += 0;
00245   current_system_time += 0;
00246 #elif defined(IPPL_XT3)
00247   double end_clock = dclock();
00248   current_clock += end_clock - last_clock;
00249 #else
00250   gettimeofday(&tvbuf, &tzbuf);
00251   times(&tmsbuf);
00252 
00253   current_secs += tvbuf.tv_sec - last_secs;
00254   current_usecs += tvbuf.tv_usec - last_usecs;
00255   current_user_time += tmsbuf.tms_utime - last_user_time;
00256   current_system_time += tmsbuf.tms_stime - last_system_time;
00257 #endif
00258 
00259   //  Set the state of the Timer
00260   timer_state = TIMEROFF;
00261   return;
00262 #endif // __MWERKS__
00263 }
00264 /*                      END OF FUNCTION stop                            */
00265 
00266 /************************************************************************/
00267 /*                                                                      */
00268 /*                      FUNCTION clock_time                             */
00269 /*                                                                      */
00270 /*      clock_time returns the current amount of real (clock) time      */
00271 /*  accumulated by this timer.  If the timer is stopped, this is just   */
00272 /*  the total accumulated time.  If the timer is running, this is the   */
00273 /*  accumulated time plus the time since the timer was last started.    */
00274 /*                                                                      */
00275 /************************************************************************/
00276 
00277 double Timer::clock_time()
00278 {
00279   TAU_PROFILE("Timer::clock_time()", "double ()", TAU_UTILITY );
00280 
00281 #ifdef __MWERKS__
00282   // For now, stub out all Timer guts for MetroWerks
00283   return 0.0;
00284 #else
00285 
00286 #if !defined(IPPL_XT3)
00287   long seconds;     // seconds elapsed
00288   
00289 #if !defined(IPPL_T3E)
00290   long useconds;    // useconds (mirco-seconds) elapsed
00291 #endif
00292 
00293 #endif
00294 
00295   double ret_val;    // time elpased
00296 
00297   if (timer_state == TIMEROFF)
00298     {
00299       // Timer is currently off, so just return accumulated time
00300 #if !defined(IPPL_XT3)
00301       seconds = current_secs;
00302       
00303 #if !defined(IPPL_T3E)
00304       useconds = current_usecs;
00305 #endif
00306 
00307 #else
00308       ret_val = current_clock;
00309 #endif
00310     }
00311   else
00312     {
00313       // Timer is currently running, so add the elapsed
00314       // time since the timer was last started to the
00315       // accumulated time
00316 #if defined(IPPL_T3E)
00317       long end_time = rtclock();
00318       seconds = current_secs + end_time - last_secs;
00319 #elif defined(IPPL_XT3)
00320       double end_clock = dclock();
00321       ret_val = current_clock + end_clock - last_clock;
00322 #else
00323       gettimeofday(&tvbuf, &tzbuf);
00324 
00325       seconds = current_secs + tvbuf.tv_sec - last_secs;
00326       useconds = current_usecs + tvbuf.tv_usec - last_usecs;
00327 #endif
00328     }
00329 
00330   //  Convert into floating point number of seconds
00331 #if defined(IPPL_T3E)
00332   ret_val = tick_secs(seconds, cpu_speed);
00333 #elif defined(IPPL_XT3)
00334   // no need to convert
00335 #else
00336   //  Adjust for the fact that the useconds may be negative.
00337   //  If they are, take away 1 second and add 1 million
00338   //  microseconds until they are positive
00339   while (useconds < 0)
00340     {
00341       useconds = useconds + 1000000;
00342       seconds = seconds - 1;
00343     }
00344 
00345   long long_ret_val = (1000000 * seconds) + useconds;
00346   ret_val = ( (double) long_ret_val ) / 1000000.0;
00347 #endif
00348 
00349   return ret_val;
00350   
00351 #endif // __MWERKS__
00352 }
00353 /*                      END OF FUNCTION clock_time                      */
00354 
00355 /************************************************************************/
00356 /*                                                                      */
00357 /*                      FUNCTION user_time                              */
00358 /*                                                                      */
00359 /*      user_time reports the current amount of user cpu time           */
00360 /*   accumulated by this Timer.  If the timer is currently off,         */
00361 /*   this is just the accumulated time.  If the Timer is running, this  */
00362 /*   is the accumulated time plust the time since the timer was last    */
00363 /*   started.                                                           */
00364 /*                                                                      */
00365 /************************************************************************/
00366 
00367 double Timer::user_time()
00368 {
00369   TAU_PROFILE("Timer::user_time()", "double ()", TAU_UTILITY );
00370 
00371 #ifdef __MWERKS__
00372 // For now, stub out all Timer guts for MetroWerks
00373   return 0.0;
00374 #else
00375   double ret_val;               //  Return value        
00376 
00377 #if ( defined(IPPL_T3E) || defined(IPPL_XT3) )
00378   // Not defined yet on T3E or TFLOP.
00379   // ERRORMSG("user_time() not defined." << endl);
00380   ret_val = -9999.0;
00381 #else
00382   if (timer_state == TIMEROFF)
00383     {
00384       //  Timer is off, just return accumulated time
00385       ret_val = current_user_time;
00386     }
00387   else
00388     {
00389       //  Timer is on, add current running time to accumulated time
00390       times(&tmsbuf);
00391       ret_val = current_user_time + tmsbuf.tms_utime - last_user_time;
00392     }
00393 
00394   //  Convert from clock ticks to seconds using the
00395   //  cpu_speed value obtained by the constructor
00396   ret_val = ret_val / cpu_speed;
00397 #endif
00398 
00399   return ret_val;
00400 #endif // __MWERKS__
00401 }
00402 /*                      END OF FUNCTION user_time                       */
00403 
00404 /************************************************************************/
00405 /*                                                                      */
00406 /*                      FUNCTION system_time                            */
00407 /*                                                                      */
00408 /*      system_time reports the current amount of system cpu time       */
00409 /*   accumulated by this Timer.  If the timer is currently off,         */
00410 /*   this is just the accumulated time.  If the Timer is running, this  */
00411 /*   is the accumulated time plus the time since the timer was last     */
00412 /*   started.                                                           */
00413 /*                                                                      */
00414 /************************************************************************/
00415 
00416 double Timer::system_time()
00417 {
00418   TAU_PROFILE("Timer::system_time()", "double ()", TAU_UTILITY );
00419 
00420 #ifdef __MWERKS__
00421 // For now, stub out all Timer guts for MetroWerks
00422   return 0.0;
00423 #else
00424   double ret_val;               //  Return value
00425 
00426 #if ( defined(IPPL_T3E) || (IPPL_XT3) )
00427   // Not defined yet on T3E or TFLOP.
00428   // ERRORMSG("system_time() not defined." << endl);
00429   ret_val = -9999.0;
00430 #else
00431   if (timer_state == TIMEROFF)
00432     {
00433       //  Timer is off, just return accumulated time
00434       ret_val = current_system_time;
00435     }
00436   else
00437     {
00438       //  Timer is on, return accumulated plus current
00439       times(&tmsbuf);
00440       ret_val = current_system_time + tmsbuf.tms_stime - last_system_time;
00441     }
00442 
00443   //  Convert from clock ticks to seconds using the
00444   //  cpu_speed value obtained by the constructor
00445   ret_val = ret_val / cpu_speed;
00446 #endif
00447 
00448   return ret_val;
00449 #endif // __MWERKS__
00450 }
00451 /*                      END OF FUNCTION system_time                     */
00452 /***************************************************************************
00453  * $RCSfile: Timer.cpp,v $   $Author: adelmann $
00454  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:33 $
00455  * IPPL_VERSION_ID: $Id: Timer.cpp,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $ 
00456  ***************************************************************************/

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