1 // -*- C++ -*-
2 /***************************************************************************
3  * blitz/Timer.h        Timer class, for use in benchmarking
4  *
5  * $Id$
6  *
7  * Copyright (C) 1997-2011 Todd Veldhuizen <tveldhui@acm.org>
8  *
9  * This file is a part of Blitz.
10  *
11  * Blitz is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation, either version 3
14  * of the License, or (at your option) any later version.
15  *
16  * Blitz is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with Blitz.  If not, see <http://www.gnu.org/licenses/>.
23  *
24  * Suggestions:          blitz-devel@lists.sourceforge.net
25  * Bugs:                 blitz-support@lists.sourceforge.net
26  *
27  * For more information, please see the Blitz++ Home Page:
28  *    https://sourceforge.net/projects/blitz/
29  *
30  ***************************************************************************/
31 
32 // This class is not portable to non System V platforms.
33 // It will need to be rewritten for Windows, NT, Mac.
34 // NEEDS_WORK
35 
36 #ifndef BZ_TIMER_H
37 #define BZ_TIMER_H
38 
39 #ifndef BZ_BLITZ_H
40  #include <blitz/blitz.h>
41 #endif
42 
43 #ifdef BZ_HAVE_RUSAGE
44  #include <sys/resource.h>
45 #else
46  #include <time.h>
47 #endif
48 
49 namespace blitz {
50 
51 #ifndef BZ_HAVE_LIBPAPI
52 
53 class Timer {
54 
55 public:
Timer()56     Timer()
57     {
58         state_ = uninitialized;
59     }
60 
start()61     void start()
62     {
63         state_ = running;
64         t1_ = systemTime();
65     }
66 
stop()67     void stop()
68     {
69         t2_ = systemTime();
70         BZPRECONDITION(state_ == running);
71         state_ = stopped;
72     }
73 
74 /* Compaq cxx compiler in ansi mode cannot print out long double type! */
75 #if defined(__DECCXX)
elapsed()76     double elapsed() const
77 #else
78     /** Return elapsed time in seconds. */
79     double elapsed() const
80 #endif
81     {
82         BZPRECONDITION(state_ == stopped);
83         return (t2_ - t1_)/1e6;
84     }
85 
instr()86   long long instr() const { return 0; };
flops()87   long long flops() const { return 0; };
88 
indep_var()89   static const string& indep_var() { return ivar_; };
90 
91 private:
Timer(Timer &)92     Timer(Timer&) { }
93     void operator=(Timer&) { }
94 
systemTime()95     long int systemTime()
96     {
97 #ifdef BZ_HAVE_RUSAGE
98         getrusage(RUSAGE_SELF, &resourceUsage_);
99         long int sec = resourceUsage_.ru_utime.tv_sec
100             + resourceUsage_.ru_stime.tv_sec;
101         long int usec  = resourceUsage_.ru_utime.tv_usec
102             + resourceUsage_.ru_stime.tv_usec;
103         return sec*1000000+usec;
104 #else
105         return 1000000*clock() / (long int) CLOCKS_PER_SEC;
106 #endif
107     }
108 
109     enum { uninitialized, running, stopped } state_;
110 
111   static const string ivar_;
112 
113 #ifdef BZ_HAVE_RUSAGE
114     struct rusage resourceUsage_;
115 #endif
116 
117     long int t1_, t2_;
118 };
119 
120 #else
121 
122 // implementation using PAPI performance counters
123 
124 #include <papi.h>
125 
126 class Timer {
127 
128 public:
129     Timer()
130     {
131       // maybe overhead is less from just reading counters
132       if(PAPI_start_counters((int*)Events, nevents)!=PAPI_OK) {
133 	cerr << "Error starting counters\n";
134       }
135       state_ = uninitialized;
136     }
137   ~Timer()
138     {
139       PAPI_stop_counters(counters_.data(), nevents);
140     }
141 
142     void start()
143     {
144         state_ = running;
145 	// this resets the counters
146         PAPI_read_counters(counters_.data(), nevents);
147     }
148 
149     void stop()
150     {
151         PAPI_read_counters(counters_.data(), nevents);
152 	BZPRECONDITION(state_ == running);
153 	state_ = stopped;
154     }
155 
156   /** since we don't know the clock frequency of the processor, we
157       instead output "flops/clock cycle" which seems like a better
158       measure of code performance and not machine performance. */
159     long long elapsed() const
160     {
161         BZPRECONDITION(state_ == stopped);
162         return counters_[0];
163     }
164 
165   long long instr() const { return counters_[1]; };
166   long long flops() const { return counters_[2]; };
167 
168   static const string& indep_var() { return ivar_; };
169 
170 private:
171     Timer(Timer&) { }
172     void operator=(Timer&) { }
173 
174     enum { uninitialized, running, stopped } state_;
175 
176   static const int nevents=3;
177   static const int Events[nevents];
178   static const string ivar_;
179 
180   TinyVector<long long, nevents> counters_;
181 };
182 
183 #endif
184 
185 
186 
187 
188 }
189 
190 #endif // BZ_TIMER_H
191 
192