[ 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 std::cerr << tic_toc_diff_string(tic) <<std::endl; 00176 } 00177 00178 inline double tic_toc_diff_num(std::vector<LARGE_INTEGER> & tic) 00179 { 00180 double res = tic_toc_diff_num(tic.back()); 00181 tic.pop_back(); 00182 return res; 00183 } 00184 00185 inline std::string tic_toc_diff_string(std::vector<LARGE_INTEGER> & tic) 00186 { 00187 std::string res = tic_toc_diff_string(tic.back()); 00188 tic.pop_back(); 00189 return res; 00190 } 00191 00192 inline void tic_toc_diff(std::vector<LARGE_INTEGER> & tic) 00193 { 00194 tic_toc_diff(tic.back()); 00195 tic.pop_back(); 00196 } 00197 00198 } // unnamed namespace 00199 00200 #define USETICTOC LARGE_INTEGER tic_timer; 00201 #define USE_NESTED_TICTOC std::vector<LARGE_INTEGER> tic_timer; 00202 #define TIC QueryPerformanceCounter(&tic_timer); 00203 #define TICPUSH tic_timer.push_back(LARGE_INTEGER());\ 00204 QueryPerformanceCounter(&(tic_timer.back())); 00205 #define TOC tic_toc_diff (tic_timer); 00206 #define TOCN tic_toc_diff_num (tic_timer) 00207 #define TOCS tic_toc_diff_string(tic_timer) 00208 00209 #else 00210 00211 #if defined(VIGRA_HIRES_TIMING) && !defined(__CYGWIN__) 00212 // requires linking against librt 00213 00214 #include <time.h> 00215 00216 namespace { 00217 00218 inline double tic_toc_diff_num(timespec const & tic) 00219 { 00220 timespec toc; 00221 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &toc); 00222 return ((toc.tv_sec*1000.0 + toc.tv_nsec/1000000.0) - 00223 (tic.tv_sec*1000.0 + tic.tv_nsec/1000000.0)); 00224 } 00225 00226 inline std::string tic_toc_diff_string(timespec const & tic) 00227 { 00228 double diff = tic_toc_diff_num(tic); 00229 std::stringstream s; 00230 s << diff << " msec"; 00231 return s.str(); 00232 } 00233 00234 inline void tic_toc_diff(timespec const & tic) 00235 { 00236 std::cerr << tic_toc_diff_string(tic) << std::endl; 00237 } 00238 00239 inline double tic_toc_diff_num(std::vector<timespec> & tic) 00240 { 00241 double res = tic_toc_diff_num(tic.back()); 00242 tic.pop_back(); 00243 return res; 00244 } 00245 00246 inline std::string tic_toc_diff_string(std::vector<timespec> & tic) 00247 { 00248 std::string res = tic_toc_diff_string(tic.back()); 00249 tic.pop_back(); 00250 return res; 00251 } 00252 00253 inline void tic_toc_diff(std::vector<timespec> & tic) 00254 { 00255 tic_toc_diff(tic.back()); 00256 tic.pop_back(); 00257 } 00258 00259 } // unnamed namespace 00260 00261 #define USETICTOC timespec tic_timer; 00262 #define TIC clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tic_timer); 00263 #define TOC tic_toc_diff (tic_timer); 00264 #define TOCN tic_toc_diff_num (tic_timer) 00265 #define TOCS tic_toc_diff_string(tic_timer) 00266 #define USE_NESTED_TICTOC std::vector<timespec> tic_timer; 00267 #define TICPUSH tic_timer.push_back(timespec());\ 00268 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(tic_timer.back())); 00269 00270 #else 00271 00272 #include <sys/time.h> 00273 00274 namespace { 00275 00276 inline double tic_toc_diff_num(timeval const & tic) 00277 { 00278 timeval toc; 00279 gettimeofday(&toc, NULL); 00280 return ((toc.tv_sec*1000.0 + toc.tv_usec/1000.0) - 00281 (tic.tv_sec*1000.0 + tic.tv_usec/1000.0)); 00282 } 00283 00284 inline std::string tic_toc_diff_string(timeval const & tic) 00285 { 00286 double diff = tic_toc_diff_num(tic); 00287 std::stringstream s; 00288 s << diff << " msec"; 00289 return s.str(); 00290 } 00291 00292 inline void tic_toc_diff(timeval const & tic) 00293 { 00294 std::cerr << tic_toc_diff_string(tic)<< std::endl; 00295 } 00296 00297 inline double tic_toc_diff_num(std::vector<timeval> & tic) 00298 { 00299 double res = tic_toc_diff_num(tic.back()); 00300 tic.pop_back(); 00301 return res; 00302 } 00303 00304 inline std::string tic_toc_diff_string(std::vector<timeval> & tic) 00305 { 00306 std::string res = tic_toc_diff_string(tic.back()); 00307 tic.pop_back(); 00308 return res; 00309 } 00310 00311 inline void tic_toc_diff(std::vector<timeval> & tic) 00312 { 00313 tic_toc_diff(tic.back()); 00314 tic.pop_back(); 00315 } 00316 00317 } // unnamed namespace 00318 00319 #define USETICTOC timeval tic_timer; 00320 #define TIC gettimeofday (&tic_timer, NULL); 00321 #define TOC tic_toc_diff (tic_timer); 00322 #define TOCN tic_toc_diff_num (tic_timer) 00323 #define TOCS tic_toc_diff_string(tic_timer) 00324 #define USE_NESTED_TICTOC std::vector<timeval> tic_timer; 00325 #define TICPUSH tic_timer.push_back(timeval());\ 00326 gettimeofday(&(tic_timer.back()), NULL); 00327 00328 #endif // VIGRA_HIRES_TIMING 00329 00330 #endif // WIN32 00331 00332 // TICTOCLOOP runs the body inner_repetitions times, and minimizes the result over a number of outer_repetitions runs, 00333 // outputting the final minimal average to std::cerr 00334 #define TICTOCLOOP_BEGIN(inner_repetitions,outer_repetitions) \ 00335 { \ 00336 USETICTOC \ 00337 double tictoc_best_, tictoc_inner_repetitions_=inner_repetitions; size_t tictoc_outer_repetitions_=outer_repetitions; \ 00338 for (size_t tictoccounter_=0; tictoccounter_<tictoc_outer_repetitions_; ++tictoccounter_) { \ 00339 TIC \ 00340 for (size_t tictocinnercounter_=0; tictocinnercounter_<inner_repetitions; ++tictocinnercounter_) { \ 00341 00342 00343 #define TICTOCLOOP_END \ 00344 } \ 00345 const double tictoc_cur_ = TOCN; \ 00346 if ((tictoccounter_==0) || (tictoc_cur_ < tictoc_best_)) \ 00347 tictoc_best_ = tictoc_cur_; \ 00348 } \ 00349 std::cerr << tictoc_best_/tictoc_inner_repetitions_ \ 00350 << " msec (best-of-" << tictoc_outer_repetitions_ << ")" << std::endl; \ 00351 }\ 00352 00353 00354 00355 #else // NDEBUG 00356 00357 #define USETICTOC 00358 #define TIC 00359 #define TOC 00360 #define TOCN 0.0 00361 #define TICS "" 00362 #define USE_NESTED_TICTOC 00363 #define TICPUSH 00364 #define TICTOCLOOP_BEGIN { 00365 #define TICTOCLOOP_END } 00366 #endif // NDEBUG 00367 00368 00369 00370 #endif // VIGRA_TIMING_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|