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

html generated using doxygen and Python
vigra 1.8.0 (20 Sep 2011)