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 ***************************************************************************/