[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

vigra/timing.hxx VIGRA

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)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.9.0 (Tue Nov 6 2012)