walltimer.cc

00001 /*
00002  *  This file is part of libcxxsupport.
00003  *
00004  *  libcxxsupport is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  libcxxsupport is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with libcxxsupport; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00017  */
00018 
00019 /*
00020  *  libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
00021  *  and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
00022  *  (DLR).
00023  */
00024 
00025 /*
00026  *  This file contains functionality related to wall-clock timers
00027  *
00028  *  Copyright (C) 2010, 2011, 2012 Max-Planck-Society
00029  *  Author: Martin Reinecke
00030  */
00031 
00032 #include <iostream>
00033 #include <utility>
00034 #include <cstdio>
00035 #include <cmath>
00036 #include <algorithm>
00037 #include "walltimer.h"
00038 #include "walltime_c.h"
00039 #include "error_handling.h"
00040 
00041 using namespace std;
00042 
00043 void wallTimer::start()
00044   { start(wallTime()); }
00045 void wallTimer::stop()
00046   { stop(wallTime()); }
00047 double wallTimer::acc() const
00048   { return acc(wallTime()); }
00049 
00050 int wallTimerSet::getIndex(const string &name)
00051   {
00052   maptype::const_iterator it = lut.find(name);
00053   if (it!=lut.end())
00054     return it->second;
00055   timer.push_back(wallTimer());
00056   lut[name]=timer.size()-1;
00057   return timer.size()-1;
00058   }
00059 
00060 void wallTimerSet::start(int index)
00061   { timer[index].start(); }
00062 void wallTimerSet::stop(int index)
00063   { timer[index].stop(); }
00064 void wallTimerSet::stopstart(int index1, int index2)
00065   { double t=wallTime(); timer[index1].stop(t); timer[index2].start(t); }
00066 void wallTimerSet::reset(int index)
00067   { timer[index].reset(); }
00068 double wallTimerSet::acc(int index)
00069   { return timer[index].acc(); }
00070 void wallTimerSet::start(const string &name)
00071   { start(getIndex(name)); }
00072 void wallTimerSet::stop(const string &name)
00073   { stop(getIndex(name)); }
00074 void wallTimerSet::stopstart(const string &name1, const string &name2)
00075   { stopstart(getIndex(name1),getIndex(name2)); }
00076 void wallTimerSet::reset(const string &name)
00077   { reset(getIndex(name)); }
00078 double wallTimerSet::acc(const string &name)
00079   { return acc(getIndex(name)); }
00080 
00081 void wallTimerSet::report() const
00082   {
00083   cout << "\nWall clock timer report:" << endl;
00084   for (maptype::const_iterator it=lut.begin(); it!=lut.end(); ++it)
00085     printf("  %-15s: %10.5fs\n", it->first.c_str(), timer[it->second].acc());
00086   cout << "End wall clock timer report\n" << endl;
00087   }
00088 
00089 wallTimerSet wallTimers;
00090 
00091 namespace {
00092 
00093 class tstack_node;
00094 
00095 typedef map<string,tstack_node>::iterator Ti;
00096 typedef map<string,tstack_node>::const_iterator Tci;
00097 typedef pair<Tci,double> Tipair;
00098 
00099 class tstack_node
00100   {
00101   public:
00102     tstack_node *parent;
00103     wallTimer wt;
00104     string name;
00105     map<string,tstack_node> child;
00106 
00107     tstack_node(const string &name_, tstack_node *parent_)
00108       : parent(parent_), name(name_) {}
00109 
00110     int max_namelen() const
00111       {
00112       int res=name.length();
00113       for (Tci it=child.begin(); it!=child.end(); ++it)
00114         res=max(res,it->second.max_namelen());
00115       return res;
00116       }
00117   };
00118 
00119 tstack_node tstack_root("root",0);
00120 tstack_node *curnode=0;
00121 double overhead=0.;
00122 
00123 struct timecomp
00124   {
00125   bool operator() (const Tipair &a, const Tipair &b) const
00126     { return a.second>b.second; }
00127   };
00128 
00129 void tstack_report(const tstack_node &node, const string &indent, int twidth,
00130   int slen)
00131   {
00132   double total=node.wt.acc();
00133   vector<Tipair> tmp;
00134   for (Tci it=node.child.begin(); it!=node.child.end(); ++it)
00135     tmp.push_back(make_pair(it,it->second.wt.acc()));
00136 
00137   if (tmp.size()>0)
00138     {
00139     sort(tmp.begin(),tmp.end(),timecomp());
00140     double tsum=0;
00141     printf("%s|\n", indent.c_str());
00142     for (unsigned i=0; i<tmp.size(); ++i)
00143       {
00144       printf("%s+- %-*s:%6.2f%% (%*.4fs)\n",indent.c_str(),slen,
00145         (tmp[i].first->first).c_str(), 100*tmp[i].second/total,twidth,
00146         tmp[i].second);
00147       tstack_report(tmp[i].first->second,indent+"|  ",twidth,slen);
00148       tsum+=tmp[i].second;
00149       }
00150     printf("%s+- %-*s:%6.2f%% (%*.4fs)\n%s\n",indent.c_str(),slen,
00151       "<unaccounted>",100*(total-tsum)/total,twidth,total-tsum,indent.c_str());
00152     }
00153   }
00154 
00155 } // unnamed namespace
00156 
00157 void tstack_push(const string &name)
00158   {
00159   double t0=wallTime();
00160   if (curnode==0) curnode=&tstack_root;
00161   Ti it=curnode->child.find(name);
00162   if (it==curnode->child.end())
00163     it=curnode->child.insert (make_pair(name,tstack_node(name,curnode))).first;
00164   curnode=&(it->second);
00165   double t1=wallTime();
00166   curnode->wt.start(0.5*(t0+t1));
00167   overhead+=t1-t0;
00168   }
00169 void tstack_pop(const string &name)
00170   {
00171   double t0=wallTime();
00172   planck_assert(curnode && (curnode->name==name), "invalid tstack operation");
00173   double t1=wallTime();
00174   curnode->wt.stop(0.5*(t0+t1));
00175   curnode=curnode->parent;
00176   overhead+=t1-t0;
00177   }
00178 void tstack_pop()
00179   {
00180   double t0=wallTime();
00181   planck_assert(curnode, "invalid tstack operation");
00182   double t1=wallTime();
00183   curnode->wt.stop(0.5*(t0+t1));
00184   curnode=curnode->parent;
00185   overhead+=t1-t0;
00186   }
00187 void tstack_replace(const string &name2)
00188   {
00189   double t0=wallTime();
00190   planck_assert(curnode, "invalid tstack operation");
00191   tstack_node *savenode=curnode;
00192   curnode=curnode->parent;
00193   Ti it=curnode->child.find(name2);
00194   if (it==curnode->child.end())
00195     it=curnode->child.insert(make_pair(name2,tstack_node(name2,curnode))).first;
00196   curnode=&(it->second);
00197   double t1=wallTime();
00198   double t=0.5*(t0+t1);
00199   savenode->wt.stop(t);
00200   curnode->wt.start(t);
00201   overhead+=t1-t0;
00202   }
00203 void tstack_replace(const string &name1, const string &name2)
00204   {
00205   planck_assert(curnode && (curnode->name==name1), "invalid tstack operation");
00206   tstack_replace(name2);
00207   }
00208 
00209 void tstack_report(const string &stem)
00210   {
00211   const tstack_node *ptr = 0;
00212   for (Tci it=tstack_root.child.begin(); it!=tstack_root.child.end(); ++it)
00213     if (it->first==stem) ptr=&(it->second);
00214   planck_assert(ptr,"invalid stem");
00215   int slen=string("<unaccounted>").size();
00216   slen = max(slen,ptr->max_namelen());
00217 
00218   double total=ptr->wt.acc();
00219   printf("\nTotal wall clock time for '%s': %1.4fs\n",stem.c_str(),total);
00220 
00221   int logtime=max(1,int(log10(total)+1));
00222   tstack_report(*ptr,"",logtime+5,slen);
00223 
00224   printf("\nAccumulated timing overhead: approx. %1.4fs\n",overhead);
00225   }

Generated on Thu Oct 8 14:48:51 2015 for LevelS C++ support library