[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
vigra/timing.hxx | ![]() |
Go to the documentation of this file.
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 2008-2011 by Ullrich Koethe */ 00004 /* Cognitive Systems Group, University of Hamburg, Germany */ 00005 /* */ 00006 /* This file is part of the VIGRA computer vision library. */ 00007 /* The VIGRA Website is */ 00008 /* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ 00009 /* Please direct questions, bug reports, and contributions to */ 00010 /* ullrich.koethe@iwr.uni-heidelberg.de or */ 00011 /* vigra@informatik.uni-hamburg.de */ 00012 /* */ 00013 /* Permission is hereby granted, free of charge, to any person */ 00014 /* obtaining a copy of this software and associated documentation */ 00015 /* files (the "Software"), to deal in the Software without */ 00016 /* restriction, including without limitation the rights to use, */ 00017 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00018 /* sell copies of the Software, and to permit persons to whom the */ 00019 /* Software is furnished to do so, subject to the following */ 00020 /* conditions: */ 00021 /* */ 00022 /* The above copyright notice and this permission notice shall be */ 00023 /* included in all copies or substantial portions of the */ 00024 /* Software. */ 00025 /* */ 00026 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00027 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00028 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00029 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00030 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00031 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00032 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00033 /* OTHER DEALINGS IN THE SOFTWARE. */ 00034 /* */ 00035 /************************************************************************/ 00036 00037 00038 #ifndef VIGRA_TIMING_HXX 00039 #define VIGRA_TIMING_HXX 00040 #ifndef VIGRA_NO_TIMING 00041 00042 #include <iostream> 00043 #include <sstream> 00044 #include <vector> 00045 00046 /*! \page TimingMacros Timing macros for runtime measurements 00047 00048 <b>\#include</b> <vigra/timing.hxx> 00049 00050 These macros allow to perform execution speed measurements. Results are reported 00051 in <i>milliseconds</i>. 00052 However, note that timings below 1 msec are generally subject to round-off errors. 00053 Under LINUX, you can \#define VIGRA_HIRES_TIMING to get better 00054 accuracy, but this requires linking against librt. 00055 00056 Basic usage: 00057 \code 00058 void time_it() 00059 { 00060 USETICTOC 00061 00062 TIC 00063 ... code to be timed 00064 TOC 00065 ... untimed code 00066 TIC 00067 ... other code to be timed 00068 TOC 00069 } 00070 \endcode 00071 00072 Instead of TOC, which outputs the time difference to std::cerr, 00073 you may use TOCN (the time difference in <i>msec</i> as a double) 00074 or TOCS (the time difference as a std::string). 00075 00076 Alternatively, you can perform nested timing like so: 00077 \code 00078 void time_it() 00079 { 00080 USE_NESTED_TICTOC 00081 00082 TICPUSH 00083 ... code to be timed 00084 TICPUSH 00085 ... nested code to be timed 00086 TOC print time for nested code 00087 ... more code to be timed 00088 TOC print total time 00089 } 00090 \endcode 00091 00092 */ 00093 00094 /*! \file timing.hxx Timing macros for runtime measurements 00095 00096 This header defines timing macros for runtime measurements. See \ref TimingMacros for examples. 00097 00098 \def USETICTOC 00099 Enable timing using TIC/TOC* pairs. This macro defines temporary storage for the timing data, so it needs to precede the TIC/TOC macros in their context. 00100 \hideinitializer 00101 00102 \def USE_NESTED_TICTOC 00103 Enable timing using TICPUSH/TOC* pairs. This macro defines temporary storage for the timing data, so it needs to precede the TIC/TOC macros in their context. 00104 \hideinitializer 00105 00106 \def TIC 00107 Start timing. Requires USE_TICTOC to be defined in the current context. 00108 \hideinitializer 00109 00110 \def TOC 00111 Stop timing and output result (the time difference w.r.t. the last TIC or TICPUSH 00112 instance) to std::cerr. 00113 \hideinitializer 00114 00115 \def TICPUSH 00116 Start timing, possibly a nested block of code within some other timed code block. 00117 Requires USE_NESTED_TICTOC to be defined once in the current context. 00118 \hideinitializer 00119 00120 \def TOCN 00121 Stop timing. This macro evaluates to the time difference (w.r.t. the last TIC 00122 or TICPUSH) in msec as a double. 00123 \hideinitializer 00124 00125 \def TOCS 00126 Stop timing. This macro evaluates to the time difference (w.r.t. the last TIC 00127 or TICPUSH) as a std::string (including units). 00128 \hideinitializer 00129 00130 \def TICTOCLOOP_BEGIN(inner_repetitions,outer_repetitions) 00131 Executes the code block up to TICTOCLOOP_END outer_repetitions x 00132 inner_repetitions times. The measurement is averaged over the 00133 inner_repetitions, and the best result of the outer_repetitions is 00134 reported to std::cerr. 00135 \hideinitializer 00136 00137 \def TICTOCLOOP_END 00138 Ends the timing loop started with the TICTOCLOOP_BEGIN macro 00139 and outputs the result. 00140 \hideinitializer 00141 */ 00142 00143 00144 #ifdef _WIN32 00145 00146 #include "windows.h" 00147 00148 namespace { 00149 00150 inline double queryTimerUnit() 00151 { 00152 LARGE_INTEGER frequency; 00153 QueryPerformanceFrequency(&frequency); 00154 return 1000.0 / frequency.QuadPart; 00155 } 00156 00157 inline double tic_toc_diff_num(LARGE_INTEGER const & tic) 00158 { 00159 LARGE_INTEGER toc; 00160 QueryPerformanceCounter(&toc); 00161 static double unit = queryTimerUnit(); 00162 return ((toc.QuadPart - tic.QuadPart) * unit); 00163 } 00164 00165 inline std::string tic_toc_diff_string(LARGE_INTEGER const & tic) 00166 { 00167 double diff = tic_toc_diff_num(tic); 00168 std::stringstream s; 00169 s << diff << " msec"; 00170 return s.str(); 00171 } 00172 00173 inline void tic_toc_diff(LARGE_INTEGER const & tic) 00174 { 00175 double diff = tic_toc_diff_num(tic); 00176 std::cerr << diff << " msec" << std::endl; 00177 } 00178 00179 inline double tic_toc_diff_num(std::vector<LARGE_INTEGER> & tic) 00180 { 00181 double res = tic_toc_diff_num(tic.back()); 00182 tic.pop_back(); 00183 return res; 00184 } 00185 00186 inline std::string tic_toc_diff_string(std::vector<LARGE_INTEGER> & tic) 00187 { 00188 std::string res = tic_toc_diff_string(tic.back()); 00189 tic.pop_back(); 00190 return res; 00191 } 00192 00193 inline void tic_toc_diff(std::vector<LARGE_INTEGER> & tic) 00194 { 00195 tic_toc_diff(tic.back()); 00196 tic.pop_back(); 00197 } 00198 00199 } // unnamed namespace 00200 00201 #define USETICTOC LARGE_INTEGER tic_timer; 00202 #define USE_NESTED_TICTOC std::vector<LARGE_INTEGER> tic_timer; 00203 #define TIC QueryPerformanceCounter(&tic_timer); 00204 #define TICPUSH tic_timer.push_back(LARGE_INTEGER());\ 00205 QueryPerformanceCounter(&(tic_timer.back())); 00206 #define TOC tic_toc_diff (tic_timer); 00207 #define TOCN tic_toc_diff_num (tic_timer) 00208 #define TOCS tic_toc_diff_string(tic_timer) 00209 00210 #else 00211 00212 #if defined(VIGRA_HIRES_TIMING) && !defined(__CYGWIN__) 00213 // requires linking against librt 00214 00215 #include <time.h> 00216 00217 namespace { 00218 00219 inline double tic_toc_diff_num(timespec const & tic) 00220 { 00221 timespec toc; 00222 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &toc); 00223 return ((toc.tv_sec*1000.0 + toc.tv_nsec/1000000.0) - 00224 (tic.tv_sec*1000.0 + tic.tv_nsec/1000000.0)); 00225 } 00226 00227 inline std::string tic_toc_diff_string(timespec const & tic) 00228 { 00229 double diff = tic_toc_diff_num(tic); 00230 std::stringstream s; 00231 s << diff << " msec"; 00232 return s.str(); 00233 } 00234 00235 inline void tic_toc_diff(timespec const & tic) 00236 { 00237 std::cerr << tic_toc_diff_string(tic) << std::endl; 00238 } 00239 00240 inline double tic_toc_diff_num(std::vector<timespec> & tic) 00241 { 00242 double res = tic_toc_diff_num(tic.back()); 00243 tic.pop_back(); 00244 return res; 00245 } 00246 00247 inline std::string tic_toc_diff_string(std::vector<timespec> & tic) 00248 { 00249 std::string res = tic_toc_diff_string(tic.back()); 00250 tic.pop_back(); 00251 return res; 00252 } 00253 00254 inline void tic_toc_diff(std::vector<timespec> & tic) 00255 { 00256 tic_toc_diff(tic.back()); 00257 tic.pop_back(); 00258 } 00259 00260 } // unnamed namespace 00261 00262 #define USETICTOC timespec tic_timer; 00263 #define TIC clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tic_timer); 00264 #define TOC tic_toc_diff (tic_timer); 00265 #define TOCN tic_toc_diff_num (tic_timer) 00266 #define TOCS tic_toc_diff_string(tic_timer) 00267 #define USE_NESTED_TICTOC std::vector<timespec> tic_timer; 00268 #define TICPUSH tic_timer.push_back(timespec());\ 00269 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(tic_timer.back())); 00270 00271 #else 00272 00273 #include <sys/time.h> 00274 00275 namespace { 00276 00277 inline double tic_toc_diff_num(timeval const & tic) 00278 { 00279 timeval toc; 00280 gettimeofday(&toc, NULL); 00281 return ((toc.tv_sec*1000.0 + toc.tv_usec/1000.0) - 00282 (tic.tv_sec*1000.0 + tic.tv_usec/1000.0)); 00283 } 00284 00285 inline std::string tic_toc_diff_string(timeval const & tic) 00286 { 00287 double diff = tic_toc_diff_num(tic); 00288 std::stringstream s; 00289 s << diff << " msec"; 00290 return s.str(); 00291 } 00292 00293 inline void tic_toc_diff(timeval const & tic) 00294 { 00295 std::cerr << tic_toc_diff_string(tic)<< std::endl; 00296 } 00297 00298 inline double tic_toc_diff_num(std::vector<timeval> & tic) 00299 { 00300 double res = tic_toc_diff_num(tic.back()); 00301 tic.pop_back(); 00302 return res; 00303 } 00304 00305 inline std::string tic_toc_diff_string(std::vector<timeval> & tic) 00306 { 00307 std::string res = tic_toc_diff_string(tic.back()); 00308 tic.pop_back(); 00309 return res; 00310 } 00311 00312 inline void tic_toc_diff(std::vector<timeval> & tic) 00313 { 00314 tic_toc_diff(tic.back()); 00315 tic.pop_back(); 00316 } 00317 00318 } // unnamed namespace 00319 00320 #define USETICTOC timeval tic_timer; 00321 #define TIC gettimeofday (&tic_timer, NULL); 00322 #define TOC tic_toc_diff (tic_timer); 00323 #define TOCN tic_toc_diff_num (tic_timer) 00324 #define TOCS tic_toc_diff_string(tic_timer) 00325 #define USE_NESTED_TICTOC std::vector<timeval> tic_timer; 00326 #define TICPUSH tic_timer.push_back(timeval());\ 00327 gettimeofday(&(tic_timer.back()), NULL); 00328 00329 #endif // VIGRA_HIRES_TIMING 00330 00331 #endif // _WIN32 00332 00333 // TICTOCLOOP runs the body inner_repetitions times, and minimizes the result over a number of outer_repetitions runs, 00334 // outputting the final minimal average to std::cerr 00335 // We enclose the loop in a dummy do { ... } while(false) in order to make this a true single statement 00336 // (instead of just a scope). 00337 #define TICTOCLOOP_BEGIN(inner_repetitions,outer_repetitions) \ 00338 do { \ 00339 USETICTOC \ 00340 double tictoc_best_, tictoc_inner_repetitions_=inner_repetitions; size_t tictoc_outer_repetitions_=outer_repetitions; \ 00341 for (size_t tictoccounter_=0; tictoccounter_<tictoc_outer_repetitions_; ++tictoccounter_) { \ 00342 TIC \ 00343 for (size_t tictocinnercounter_=0; tictocinnercounter_<inner_repetitions; ++tictocinnercounter_) { \ 00344 00345 00346 #define TICTOCLOOP_END \ 00347 } \ 00348 const double tictoc_cur_ = TOCN; \ 00349 if ((tictoccounter_==0) || (tictoc_cur_ < tictoc_best_)) \ 00350 tictoc_best_ = tictoc_cur_; \ 00351 } \ 00352 std::cerr << tictoc_best_/tictoc_inner_repetitions_ \ 00353 << " msec (best-of-" << tictoc_outer_repetitions_ << ")" << std::endl; \ 00354 } while(false); 00355 00356 00357 00358 #else // NDEBUG 00359 00360 #define USETICTOC 00361 #define TIC 00362 #define TOC 00363 #define TOCN 0.0 00364 #define TICS "" 00365 #define USE_NESTED_TICTOC 00366 #define TICPUSH 00367 #define TICTOCLOOP_BEGIN(inner_repetitions,outer_repetitions) do { 00368 #define TICTOCLOOP_END } while(false); 00369 #endif // NDEBUG 00370 00371 00372 00373 #endif // VIGRA_TIMING_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|