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