LevelS C++ support library  3.50
walltimer.cc
1 /*
2  * This file is part of libcxxsupport.
3  *
4  * libcxxsupport is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * libcxxsupport is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with libcxxsupport; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /*
20  * libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
21  * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
22  * (DLR).
23  */
24 
25 /*
26  * This file contains functionality related to wall-clock timers
27  *
28  * Copyright (C) 2010, 2011, 2012 Max-Planck-Society
29  * Author: Martin Reinecke
30  */
31 
32 #include <iostream>
33 #include <utility>
34 #include <cstdio>
35 #include <cmath>
36 #include <algorithm>
37 #include "walltimer.h"
38 #include "walltime_c.h"
39 #include "error_handling.h"
40 
41 using namespace std;
42 
43 void wallTimer::start()
44  { start(wallTime()); }
45 void wallTimer::stop()
46  { stop(wallTime()); }
47 double wallTimer::acc() const
48  { return acc(wallTime()); }
49 
50 int wallTimerSet::getIndex(const string &name)
51  {
52  maptype::const_iterator it = lut.find(name);
53  if (it!=lut.end())
54  return it->second;
55  timer.push_back(wallTimer());
56  lut[name]=timer.size()-1;
57  return timer.size()-1;
58  }
59 
60 void wallTimerSet::start(int index)
61  { timer[index].start(); }
62 void wallTimerSet::stop(int index)
63  { timer[index].stop(); }
64 void wallTimerSet::stopstart(int index1, int index2)
65  { double t=wallTime(); timer[index1].stop(t); timer[index2].start(t); }
66 void wallTimerSet::reset(int index)
67  { timer[index].reset(); }
68 double wallTimerSet::acc(int index)
69  { return timer[index].acc(); }
70 void wallTimerSet::start(const string &name)
71  { start(getIndex(name)); }
72 void wallTimerSet::stop(const string &name)
73  { stop(getIndex(name)); }
74 void wallTimerSet::stopstart(const string &name1, const string &name2)
75  { stopstart(getIndex(name1),getIndex(name2)); }
76 void wallTimerSet::reset(const string &name)
77  { reset(getIndex(name)); }
78 double wallTimerSet::acc(const string &name)
79  { return acc(getIndex(name)); }
80 
81 void wallTimerSet::report() const
82  {
83  cout << "\nWall clock timer report:" << endl;
84  for (maptype::const_iterator it=lut.begin(); it!=lut.end(); ++it)
85  printf(" %-15s: %10.5fs\n", it->first.c_str(), timer[it->second].acc());
86  cout << "End wall clock timer report\n" << endl;
87  }
88 
89 wallTimerSet wallTimers;
90 
91 namespace {
92 
93 class tstack_node;
94 
95 typedef map<string,tstack_node>::iterator Ti;
96 typedef map<string,tstack_node>::const_iterator Tci;
97 typedef pair<Tci,double> Tipair;
98 
99 class tstack_node
100  {
101  public:
102  tstack_node *parent;
103  wallTimer wt;
104  string name;
105  map<string,tstack_node> child;
106 
107  tstack_node(const string &name_, tstack_node *parent_)
108  : parent(parent_), name(name_) {}
109 
110  int max_namelen() const
111  {
112  int res=name.length();
113  for (Tci it=child.begin(); it!=child.end(); ++it)
114  res=max(res,it->second.max_namelen());
115  return res;
116  }
117  };
118 
119 tstack_node tstack_root("root",0);
120 tstack_node *curnode=0;
121 double overhead=0.;
122 
123 struct timecomp
124  {
125  bool operator() (const Tipair &a, const Tipair &b) const
126  { return a.second>b.second; }
127  };
128 
129 void tstack_report(const tstack_node &node, const string &indent, int twidth,
130  int slen)
131  {
132  double total=node.wt.acc();
133  vector<Tipair> tmp;
134  for (Tci it=node.child.begin(); it!=node.child.end(); ++it)
135  tmp.push_back(make_pair(it,it->second.wt.acc()));
136 
137  if (tmp.size()>0)
138  {
139  sort(tmp.begin(),tmp.end(),timecomp());
140  double tsum=0;
141  printf("%s|\n", indent.c_str());
142  for (unsigned i=0; i<tmp.size(); ++i)
143  {
144  printf("%s+- %-*s:%6.2f%% (%*.4fs)\n",indent.c_str(),slen,
145  (tmp[i].first->first).c_str(), 100*tmp[i].second/total,twidth,
146  tmp[i].second);
147  tstack_report(tmp[i].first->second,indent+"| ",twidth,slen);
148  tsum+=tmp[i].second;
149  }
150  printf("%s+- %-*s:%6.2f%% (%*.4fs)\n%s\n",indent.c_str(),slen,
151  "<unaccounted>",100*(total-tsum)/total,twidth,total-tsum,indent.c_str());
152  }
153  }
154 
155 } // unnamed namespace
156 
157 void tstack_push(const string &name)
158  {
159  double t0=wallTime();
160  if (curnode==0) curnode=&tstack_root;
161  Ti it=curnode->child.find(name);
162  if (it==curnode->child.end())
163  it=curnode->child.insert (make_pair(name,tstack_node(name,curnode))).first;
164  curnode=&(it->second);
165  double t1=wallTime();
166  curnode->wt.start(0.5*(t0+t1));
167  overhead+=t1-t0;
168  }
169 void tstack_pop(const string &name)
170  {
171  double t0=wallTime();
172  planck_assert(curnode && (curnode->name==name), "invalid tstack operation");
173  double t1=wallTime();
174  curnode->wt.stop(0.5*(t0+t1));
175  curnode=curnode->parent;
176  overhead+=t1-t0;
177  }
178 void tstack_pop()
179  {
180  double t0=wallTime();
181  planck_assert(curnode, "invalid tstack operation");
182  double t1=wallTime();
183  curnode->wt.stop(0.5*(t0+t1));
184  curnode=curnode->parent;
185  overhead+=t1-t0;
186  }
187 void tstack_replace(const string &name2)
188  {
189  double t0=wallTime();
190  planck_assert(curnode, "invalid tstack operation");
191  tstack_node *savenode=curnode;
192  curnode=curnode->parent;
193  Ti it=curnode->child.find(name2);
194  if (it==curnode->child.end())
195  it=curnode->child.insert(make_pair(name2,tstack_node(name2,curnode))).first;
196  curnode=&(it->second);
197  double t1=wallTime();
198  double t=0.5*(t0+t1);
199  savenode->wt.stop(t);
200  curnode->wt.start(t);
201  overhead+=t1-t0;
202  }
203 void tstack_replace(const string &name1, const string &name2)
204  {
205  planck_assert(curnode && (curnode->name==name1), "invalid tstack operation");
206  tstack_replace(name2);
207  }
208 
209 void tstack_report(const string &stem)
210  {
211  const tstack_node *ptr = 0;
212  for (Tci it=tstack_root.child.begin(); it!=tstack_root.child.end(); ++it)
213  if (it->first==stem) ptr=&(it->second);
214  planck_assert(ptr,"invalid stem");
215  int slen=string("<unaccounted>").size();
216  slen = max(slen,ptr->max_namelen());
217 
218  double total=ptr->wt.acc();
219  printf("\nTotal wall clock time for '%s': %1.4fs\n",stem.c_str(),total);
220 
221  int logtime=max(1,int(log10(total)+1));
222  tstack_report(*ptr,"",logtime+5,slen);
223 
224  printf("\nAccumulated timing overhead: approx. %1.4fs\n",overhead);
225  }
#define planck_assert(testval, msg)
double wallTime(void)

Generated on Mon Dec 10 2018 10:24:20 for LevelS C++ support library