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