Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:17:27

0001 #ifndef PHOOL_PHTIMER_H
0002 #define PHOOL_PHTIMER_H
0003 
0004 /*!
0005 \file       PHTimer.h
0006 \brief   high precision timer
0007 \author Sean Kelly, Hugo Pereira
0008 \version $Revision: 1.6 $
0009 \date       $Date: 2013/01/07 09:27:01 $
0010 */
0011 
0012 #include <unistd.h>
0013 #include <exception>
0014 #include <iostream>
0015 #include <sstream>
0016 #include <string>
0017 
0018 #define rdtsc(low, high)       \
0019   __asm__ __volatile__("rdtsc" \
0020                        : "=a"(low), "=d"(high))
0021 
0022 /*! \ingroup classes */
0023 //! high precision timer
0024 /*! high precision timer */
0025 class PHTimer
0026 {
0027  public:
0028   //! enum for timer state
0029   enum State
0030   {
0031     STOP = 0,
0032     RUN = 1
0033   };
0034 
0035   //! access timer state
0036   State get_state(void) const
0037   {
0038     return _state;
0039   }
0040 
0041   //! Construct with a name
0042   explicit PHTimer(const std::string& name = "Generic Timer")
0043     : _name(name)
0044     , _state(STOP)
0045     , _start_time(get_clock_counts())
0046     , _stop_time(get_clock_counts())
0047   {
0048     _stop_time._low++;
0049   }
0050 
0051   //! stops the counter
0052   void stop()
0053   {
0054     if (_state == STOP) return;
0055     _stop_time = get_clock_counts();
0056     _state = STOP;
0057     _ncycle++;
0058     _accumulated_time += elapsed();
0059   }
0060 
0061   //! Restart timer
0062   void restart()
0063   {
0064     _start_time = get_clock_counts();
0065     _state = RUN;
0066   }
0067 
0068   //! Dump elapsed time to provided ostream
0069   void print(std::ostream& os = std::cout) const
0070   {
0071     double elapse(elapsed());
0072     PRINT(os, "Timing for " + _name);
0073     os << "time (ms): " << elapse << std::endl;
0074     PRINT();
0075   }
0076 
0077   //! Dump statistics
0078   void print_stat(std::ostream& os = std::cout) const
0079   {
0080     //   PRINT(os, std::string("Stats for " + _name));
0081     if (_ncycle)
0082     {
0083       os << _name << ": accumulated time (ms):  " << _accumulated_time << std::endl;
0084       os << _name << ": per event time (ms):    " << _accumulated_time / _ncycle << std::endl;
0085     }
0086     else
0087     {
0088       os << _name << ": timer never started.\n";
0089     }
0090     PRINT(os, "**");
0091   }
0092 
0093   //! Set timer name
0094   void set_name(const std::string& name)
0095   {
0096     _name = name;
0097   }
0098 
0099   //! get timer name
0100   const std::string& get_name(void) const
0101   {
0102     return _name;
0103   }
0104 
0105   //! get cumulated time
0106   double get_accumulated_time(void) const
0107   {
0108     return _accumulated_time;
0109   }
0110 
0111   //! get number of cycles
0112   unsigned int get_ncycle(void) const
0113   {
0114     return _ncycle;
0115   }
0116 
0117   //! get averaged time/cycle
0118   double get_time_per_cycle(void) const
0119   {
0120     return _accumulated_time / _ncycle;
0121   }
0122 
0123   //! retrieve elapsed value since last restart (in ms)
0124   double elapsed(void) const
0125   {
0126     return 1000.0 * get_difference(
0127                         (_state == RUN) ? get_clock_counts() : _stop_time,
0128                         _start_time);
0129   }
0130 
0131   //! test PHTimer for a given amount of time (in ms)
0132   void test(double time, std::ostream& os = std::cout)
0133   {
0134     std::ostringstream tmp;
0135     tmp << "Test for " << _name << " - " << time << "ms";
0136     PRINT(os, tmp.str());
0137     restart();
0138     usleep((unsigned int) (time * 1000));
0139     print(os);
0140   }
0141 
0142   //! print a message (formated) to a stream
0143   static void PRINT(std::ostream& os = std::cout, const std::string& message = "");
0144 
0145  private:
0146   //! internal frequency read from cpu information file
0147   class Frequency
0148   {
0149    public:
0150     //! constructor
0151     Frequency()
0152     {
0153       try
0154       {
0155         set_cpu_freq();
0156       }
0157       catch (std::exception& e)
0158       {
0159         std::cout << e.what() << std::endl;
0160       }
0161       _period = 1.0 / _frequency;
0162     }
0163 
0164     //! frequency accessor
0165     operator double() const
0166     {
0167       return _frequency;
0168     }
0169 
0170     //! period accessor
0171     double period() const
0172     {
0173       return _period;
0174     }
0175 
0176    private:
0177     //! pc frequency
0178     double _frequency;
0179 
0180     //! pc period
0181     double _period;
0182 
0183     //! read pc frequency from cpuinfo place
0184     void set_cpu_freq(const std::string& cpuinfopath = "/proc/cpuinfo");
0185   };
0186 
0187   //! used to store high precision time using two integers
0188   struct time_struct
0189   {
0190     //! constructor
0191     time_struct(void) = default;
0192 
0193     //! low wheight bits cpu count
0194     unsigned long _low{0};
0195 
0196     //! high wheight bits cpu count
0197     unsigned long _high{0};
0198   };
0199 
0200   //! gets time from cpu clock counts
0201   static time_struct get_clock_counts(void)
0202   {
0203     time_struct t;
0204     rdtsc(t._low, t._high);
0205     return t;
0206   }
0207 
0208   //! returns difference between to time
0209   static double get_difference(
0210       const time_struct&,
0211       const time_struct&);
0212 
0213   //! static frequency object
0214   static Frequency _frequency;
0215 
0216   //! to stores 2^32
0217   static const double _twopower32;
0218 
0219   //! timer name
0220   std::string _name;
0221 
0222   //! timer state
0223   State _state;
0224 
0225   //! start time structure
0226   time_struct _start_time;
0227 
0228   //! stop time structure
0229   time_struct _stop_time;
0230 
0231   //! cumulated time
0232   double _accumulated_time{0};
0233 
0234   //! number of restart/stop cycles
0235   unsigned int _ncycle{0};
0236 };
0237 
0238 #endif