StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ProgressLog.h
1 // ProgressLog.h is a part of the PYTHIA event generator.
2 // Copyright (C) 2018 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL v2 or later, see COPYING for details.
4 // Please respect the MCnet Guidelines, see GUIDELINES for details.
5 
6 #ifndef PROGRESSLOG_H
7 #define PROGRESSLOG_H
8 
9 #include <ctime>
10 #include <sys/times.h>
11 #include <unistd.h>
12 
13 namespace Pythia8 {
14 
15 using namespace std;
16 
17 // ProgressLog is a simple helper class to monitor the progress of a run.
18 // When used in the main event loop, it will with suitably (logarithmically)
19 // spaced intervals, print out one line with information about the number
20 // of events generated, two estimates (based on instantaneous and average
21 // CPU consumption) of when the run will be completed, the host on which
22 // the program is run and its process number.
23 
24 class ProgressLog {
25 
26 public:
27 
28  // Create an object for monitoring the progress of a run with NIn iterations.
29  ProgressLog( long NIn, int maxsec = 1200) : secstep(maxsec) {
30  init(NIn);
31  }
32 
33  // Intermittently write out a line of progress information, giving
34  // the current iteration (in the interval [0:N[ ).
35  void operator()(int cnt) {
36  tick(cnt + 1, N);
37  }
38 
39  // Intermittently write out a line of progress information using the
40  // internal counter.
41  void operator()() {
42  tick(++count, N);
43  }
44 
45  // Intermittently write out a line of progress information giving
46  // the current iteration and the total number of iterations.
47  void tick(long i, long n) {
48  if ( !statusTime(i, n) ) return;
49 
50  double fcpui = fclock();
51  time_t timei = time(0);
52  double ftime0 = time0;
53  double ftime1 = time1;
54  double ftimei = timei;
55  double eff = 1.0;
56  if ( ftimei > ftime1 && fcpui > fcpu1 )
57  eff = (fcpui-fcpu1)/(ftimei-ftime1);
58  if ( eff >= 1.0 ) eff = 0.999999;
59  int ieff = 100*eff;
60  double eff0 = 1.0;
61  if ( ftimei > ftime0 && fcpui > fcpu0 )
62  eff0 = (fcpui-fcpu0)/(ftimei-ftime0);
63  if ( eff0 >= 1.0 ) eff0 = 0.999999;
64  int ieff0 = 100*eff0;
65  double fcpun = fcpu0 + (n*(fcpui-fcpu0))/i;
66  time_t timen = (time_t)(ftimei + (fcpun-fcpui)/eff + 30.0);
67  time_t timen0 = (time_t)(ftimei + (fcpun-fcpui)/eff0 + 30.0);
68  char date[1024];
69  char daten[1024];
70  char daten0[1024];
71  strftime(date,1024,"%y.%m.%d %H:%M",localtime(&timei));
72  strftime(daten,1024,"%H:%M",localtime(&timen));
73  strftime(daten0,1024,"%H:%M",localtime(&timen0));
74  long ii = i;
75  if ( n - i < n/10 ) ii = i - n;
76  time_t dayn = (timen - timei)/86400;
77  time_t dayn0 = (timen0 - timei)/86400;
78 
79  ostream & os = cout;
80 
81  if ( dayn <= 0 && dayn0 <= 0 ) {
82  os << date << " " << setw(8) << ii << "/" << setw(9);
83  os.setf(ios::left, ios::adjustfield);
84  os << n << " etc: " << daten << "[";
85  os.setf(ios::right, ios::adjustfield);
86  os << setw(2) << ieff << "%] " << daten0 << "[" << ieff0 << "%] "
87  << host << ":" << pid << endl << flush;
88  } else {
89  os << date << " " << setw(8) << ii << "/" << setw(9);
90  os.setf(ios::left, ios::adjustfield);
91  os << n << " etc: " << dayn << "+" << daten << "[";
92  os.setf(ios::right, ios::adjustfield);
93  os << setw(2) << ieff << "%] "
94  << dayn0 << "+" << daten0 << "[" << ieff0 << "%] "
95  << host << ":" << pid << endl << flush;
96  }
97 
98  fcpu1 = fcpui;
99  time1 = timei;
100 
101  }
102 
103  // Interface to the system time information.
104  double fclock() {
105  struct tms tmsbuf;
106  times(&tmsbuf);
107  double d =
108  tmsbuf.tms_utime+tmsbuf.tms_stime+tmsbuf.tms_cutime+tmsbuf.tms_cstime;
109  d /= sysconf(_SC_CLK_TCK);
110  return d;
111  }
112 
113  // Check if this is a good time to print out a status line.
114  bool statusTime(long i, long n) const {
115  if ( i <= 0 ) return false;
116  if ( i == n ) return true;
117  if ( i > n/2 ) i = n-i;
118  while ( i >= 10 && !(i%10) ) i /= 10;
119  if ( i == 1 || i == 2 || i == 5 ) return true;
120  if ( secstep > 0 && time(0) > time1 + secstep ) return true;
121  return false;
122  }
123 
124  // Initialise the basic engine.
125  void init(long n) {
126  N = n;
127  count = 0;
128  fcpu0 = fcpu1 = fclock();
129  time0 = time1 = time(0);
130  char name[1024];
131  gethostname(name,1024);
132  host = name;
133  if ( host.find(".") != string::npos )
134  host = host.substr(0, host.find("."));
135  pid = getpid();
136  char date[1024];
137  strftime(date,1024,"%y.%m.%d %H:%M",localtime(&time0));
138  ostream & os = cout;
139  os << date << " 0/" << setw(9);
140  os.setf(ios::left, ios::adjustfield);
141  os << n;
142  os.setf(ios::right, ios::adjustfield);
143  os << " Initializing... "
144  << host << ":" << pid << endl << flush;
145  }
146 
147 private:
148 
149  // If larger than 0, a status line will be written every secstep
150  // second.
151  int secstep;
152 
153  // The clock when the run was started.
154  time_t time0;
155 
156  // The cpu clock when the run was started.
157  double fcpu0;
158 
159  // The clock the last time a status line was written out.
160  time_t time1;
161 
162  // The cpu clock the last time a status line was written out.
163  double fcpu1;
164 
165  // The host on which we are running.
166  string host;
167 
168  // The pid of the current process.
169  pid_t pid;
170 
171  // The number of iterations
172  long N;
173 
174  // The number of iterations so far
175  long count;
176 
177 };
178 
179 }
180 
181 #endif