CppAD: A C++ Algorithmic Differentiation Package  20130102
speed_test.hpp
Go to the documentation of this file.
00001 /* $Id$ */
00002 # ifndef CPPAD_SPEED_TEST_INCLUDED
00003 # define CPPAD_SPEED_TEST_INCLUDED
00004 
00005 /* --------------------------------------------------------------------------
00006 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell
00007 
00008 CppAD is distributed under multiple licenses. This distribution is under
00009 the terms of the 
00010                     Eclipse Public License Version 1.0.
00011 
00012 A copy of this license is included in the COPYING file of this distribution.
00013 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
00014 -------------------------------------------------------------------------- */
00015 
00016 /*
00017 $begin speed_test$$
00018 $spell
00019      gettimeofday
00020      vec
00021      cppad.hpp
00022      Microsoft
00023      namespace
00024      std
00025      const
00026      cout
00027      ctime
00028      ifdef
00029      const
00030      endif
00031      cpp
00032 $$
00033 
00034 $index speed_test$$
00035 $index test, speed$$
00036 
00037 $section Run One Speed Test and Return Results$$
00038 
00039 $head Syntax$$
00040 $code # include <cppad/speed_test.hpp>$$
00041 $pre
00042 $$
00043 $icode%rate_vec% = speed_test(%test%, %size_vec%, %time_min%)%$$
00044 
00045 $head Purpose$$
00046 The $code speed_test$$ function executes a speed test
00047 for various sized problems
00048 and reports the rate of execution.
00049 
00050 $head Motivation$$
00051 It is important to separate small calculation units
00052 and test them individually.
00053 This way individual changes can be tested in the context of the
00054 routine that they are in.
00055 On many machines, accurate timing of a very short execution 
00056 sequences is not possible.
00057 In addition,
00058 there may be set up and tear down time for a test that
00059 we do not really want included in the timing.
00060 For this reason $code speed_test$$
00061 automatically determines how many times to 
00062 repeat the section of the test that we wish to time.
00063 
00064 
00065 $head Include$$
00066 The file $code cppad/speed_test.hpp$$ defines the 
00067 $code speed_test$$ function.
00068 This file is included by $code cppad/cppad.hpp$$
00069 and it can also be included separately with out the rest of 
00070 the $code CppAD$$ routines.
00071 
00072 $head Vector$$
00073 We use $icode Vector$$ to denote a 
00074 $cref/simple vector class/SimpleVector/$$ with elements
00075 of type $code size_t$$.
00076 
00077 $head test$$
00078 The $code speed_test$$ argument $icode test$$ is a function with the syntax
00079 $codei%
00080      %test%(%size%, %repeat%)
00081 %$$
00082 and its return value is $code void$$.
00083 
00084 $subhead size$$
00085 The $icode test$$ argument $icode size$$ has prototype
00086 $codei%
00087      size_t %size%
00088 %$$
00089 It specifies the size for this test.
00090 
00091 $subhead repeat$$
00092 The $icode test$$ argument $icode repeat$$ has prototype
00093 $codei%
00094      size_t %repeat%
00095 %$$
00096 It specifies the number of times to repeat the test.
00097 
00098 $head size_vec$$
00099 The $code speed_test$$ argument $icode size_vec$$ has prototype
00100 $codei%
00101      const %Vector%& %size_vec%
00102 %$$
00103 This vector determines the size for each of the tests problems.
00104 
00105 $head time_min$$
00106 The argument $icode time_min$$ has prototype
00107 $codei%
00108      double %time_min%
00109 %$$
00110 It specifies the minimum amount of time in seconds
00111 that the $icode test$$ routine should take.
00112 The $icode repeat$$ argument to $icode test$$ is increased
00113 until this amount of execution time is reached.
00114 
00115 $head rate_vec$$
00116 The return value $icode rate_vec$$ has prototype
00117 $codei%
00118      %Vector%& %rate_vec%
00119 %$$ 
00120 We use $latex n$$ to denote its size which is the same as
00121 the vector $icode size_vec$$.
00122 For $latex i = 0 , \ldots , n-1$$,
00123 $codei%
00124      %rate_vec%[%i%]
00125 %$$
00126 is the ratio of $icode repeat$$ divided by time in seconds
00127 for the problem with size $icode%size_vec%[%i%]%$$.
00128 
00129 $head Timing$$
00130 If your system supports the unix $code gettimeofday$$ function,
00131 it will be used to measure time. 
00132 Otherwise, 
00133 time is measured by the difference in
00134 $codep
00135      (double) clock() / (double) CLOCKS_PER_SEC
00136 $$
00137 in the context of the standard $code <ctime>$$ definitions.
00138 
00139 $children%
00140      speed/example/speed_test.cpp
00141 %$$
00142 $head Example$$
00143 The routine $cref speed_test.cpp$$ is an example and test
00144 of $code speed_test$$.
00145 
00146 $end
00147 -----------------------------------------------------------------------
00148 */
00149 
00150 # include <cstddef>
00151 # include <cmath>
00152 
00153 # include <cppad/check_simple_vector.hpp>
00154 # include <cppad/elapsed_seconds.hpp>
00155 
00156 
00157 namespace CppAD { // BEGIN CppAD namespace
00158 
00159 // implemented as an inline so that can include in multiple link modules
00160 // with this same file
00161 template <class Vector>
00162 inline Vector speed_test( 
00163      void test(size_t size, size_t repeat),
00164      const Vector& size_vec               ,
00165      double time_min                      )
00166 {
00167      // check that size_vec is a simple vector with size_t elements
00168      CheckSimpleVector<size_t, Vector>();
00169 
00170      size_t   n = size_vec.size();
00171      Vector rate_vec(n);
00172      size_t i;
00173      for(i = 0; i < n; i++)
00174      {    size_t size   = size_vec[i];
00175           size_t repeat = 1;
00176           double s0     = elapsed_seconds();
00177           double s1     = elapsed_seconds();
00178           while( s1 - s0 < time_min )
00179           {    repeat = 2 * repeat;
00180                s0     = elapsed_seconds();
00181                test(size, repeat);
00182                s1     = elapsed_seconds();
00183           }
00184           rate_vec[i] = (size_t)(.5 + repeat / (s1 - s0));
00185      }
00186      return rate_vec;
00187 }
00188 
00189 } // END CppAD namespace
00190 
00191 /*
00192 $begin SpeedTest$$
00193 $spell
00194      cppad.hpp
00195      Microsoft
00196      namespace
00197      std
00198      const
00199      cout
00200      ctime
00201      ifdef
00202      const
00203      endif
00204      cpp
00205 $$
00206 
00207 $index SpeedTest$$
00208 $index test, speed$$
00209 
00210 $section Run One Speed Test and Print Results$$
00211 
00212 $head Syntax$$
00213 
00214 $code # include <cppad/speed_test.hpp>$$
00215 $pre
00216 $$
00217 $codei%SpeedTest(%Test%, %first%, %inc%, %last%)%$$
00218 
00219 
00220 $head Purpose$$
00221 The $code SpeedTest$$ function executes a speed test
00222 for various sized problems
00223 and reports the results on standard output; i.e. $code std::cout$$.
00224 The size of each test problem is included in its report
00225 (unless $icode first$$ is equal to $icode last$$).
00226 
00227 $head Motivation$$
00228 It is important to separate small calculation units
00229 and test them individually.
00230 This way individual changes can be tested in the context of the
00231 routine that they are in.
00232 On many machines, accurate timing of a very short execution 
00233 sequences is not possible.
00234 In addition,
00235 there may be set up time for a test that
00236 we do not really want included in the timing.
00237 For this reason $code SpeedTest$$
00238 automatically determines how many times to 
00239 repeat the section of the test that we wish to time.
00240 
00241 
00242 $head Include$$
00243 The file $code speed_test.hpp$$ contains the 
00244 $code SpeedTest$$ function.
00245 This file is included by $code cppad/cppad.hpp$$
00246 but it can also be included separately with out the rest of 
00247 the $code CppAD$$ routines.
00248 
00249 $head Test$$
00250 The $code SpeedTest$$ argument $icode Test$$ is a function with the syntax
00251 $codei%
00252      %name% = %Test%(%size%, %repeat%)
00253 %$$
00254 
00255 $subhead size$$
00256 The $icode Test$$ argument $icode size$$ has prototype
00257 $codei%
00258      size_t %size%
00259 %$$
00260 It specifies the size for this test.
00261 
00262 $subhead repeat$$
00263 The $icode Test$$ argument $icode repeat$$ has prototype
00264 $codei%
00265      size_t %repeat%
00266 %$$
00267 It specifies the number of times to repeat the test.
00268 
00269 $subhead name$$
00270 The $icode Test$$ result $icode name$$ has prototype
00271 $codei%
00272      std::string %name%
00273 %$$
00274 The results for this test are reported on $code std::cout$$
00275 with $icode name$$ as an identifier for the test.
00276 It is assumed that,
00277 for the duration of this call to $code SpeedTest$$,
00278 $icode Test$$ will always return 
00279 the same value for $icode name$$.
00280 If $icode name$$ is the empty string, 
00281 no test name is reported by $code SpeedTest$$.
00282 
00283 $head first$$
00284 The $code SpeedTest$$ argument $icode first$$ has prototype
00285 $codei%
00286      size_t %first%
00287 %$$
00288 It specifies the size of the first test problem reported by this call to 
00289 $code SpeedTest$$.
00290      
00291 $head last$$
00292 The $code SpeedTest$$ argument $icode last$$ has prototype
00293 $codei%
00294      size_t %last%
00295 %$$
00296 It specifies the size of the last test problem reported by this call to 
00297 $code SpeedTest$$.
00298 
00299 $head inc$$
00300 The $code SpeedTest$$ argument $icode inc$$ has prototype
00301 $codei%
00302      int %inc%
00303 %$$
00304 It specifies the increment between problem sizes; i.e.,
00305 all values of $icode size$$ in calls to $icode Test$$ are given by
00306 $codei%
00307      %size% = %first% + %j% * %inc%
00308 %$$ 
00309 where $icode j$$ is a positive integer.
00310 The increment can be positive or negative but it cannot be zero.
00311 The values $icode first$$, $icode last$$ and $icode inc$$ must 
00312 satisfy the relation
00313 $latex \[
00314      inc * ( last - first ) \geq 0
00315 \] $$
00316 
00317 $head rate$$
00318 The value displayed in the $code rate$$ column on $code std::cout$$
00319 is defined as the value of $icode repeat$$ divided by the 
00320 corresponding elapsed execution time in seconds.
00321 The elapsed execution time is measured by the difference in
00322 $codep
00323      (double) clock() / (double) CLOCKS_PER_SEC
00324 $$
00325 in the context of the standard $code <ctime>$$ definitions.
00326 
00327 
00328 $head Errors$$
00329 If one of the restrictions above is violated,
00330 the CppAD error handler is used to report the error.
00331 You can redefine this action using the instructions in
00332 $cref ErrorHandler$$
00333 
00334 $head Example$$
00335 $children%
00336      speed/example/speed_program.cpp
00337 %$$
00338 The program $cref speed_program.cpp$$ is an example usage
00339 of $code SpeedTest$$.
00340 
00341 $end
00342 -----------------------------------------------------------------------
00343 */
00344 // BEGIN C++
00345 
00346 
00347 # include <string>
00348 # include <iostream>
00349 # include <iomanip>
00350 # include <cppad/local/cppad_assert.hpp>
00351 
00352 namespace CppAD { // BEGIN CppAD namespace
00353 
00354 inline void SpeedTestNdigit(size_t value, size_t &ndigit, size_t &pow10)
00355 {    pow10 = 10;
00356      ndigit       = 1;
00357      while( pow10 <= value )
00358      {    pow10  *= 10;
00359           ndigit += 1;
00360      }
00361 }
00362 
00363 // implemented as an inline so that can include in multiple link modules
00364 // with this same file
00365 inline void SpeedTest( 
00366      std::string Test(size_t size, size_t repeat),
00367      size_t first,
00368      int    inc,
00369      size_t last
00370 )
00371 {
00372 
00373      using std::cout;
00374      using std::endl;
00375 
00376      size_t    size;
00377      size_t    repeat;
00378      size_t    rate;
00379      size_t    digit;
00380      size_t    ndigit;
00381      size_t    pow10;
00382      size_t    maxSize;
00383      size_t    maxSizeDigit;
00384 
00385      double    s0;
00386      double    s1;
00387 
00388      std::string name;
00389 
00390      CPPAD_ASSERT_KNOWN( 
00391           inc != 0 && first != 0 && last != 0,
00392           "inc, first, or last is zero in call to SpeedTest"
00393      );
00394      CPPAD_ASSERT_KNOWN( 
00395           (inc > 0 && first <= last) || (inc < 0 && first >= last),
00396           "SpeedTest: increment is positive and first > last or "
00397           "increment is negative and first < last"
00398      );
00399 
00400      // compute maxSize
00401      maxSize = size = first;
00402      while(  (inc > 0 && size <= last) || (inc < 0 && size >= last) )
00403      {
00404           if( size > maxSize )
00405                maxSize = size;
00406 
00407           // next size
00408           if( ((int) size) + inc > 0 )
00409                size += inc;
00410           else size  = 0;
00411      }
00412      SpeedTestNdigit(maxSize, maxSizeDigit, pow10);
00413 
00414      size = first;
00415      while(  (inc > 0 && size <= last) || (inc < 0 && size >= last) )
00416      {
00417           repeat = 1;
00418           s0     = elapsed_seconds();
00419           s1     = elapsed_seconds();
00420           while( s1 - s0 < 1. )
00421           {    repeat = 2 * repeat;
00422                s0     = elapsed_seconds();
00423                name   = Test(size, repeat);
00424                s1     = elapsed_seconds();
00425           }
00426           rate = (size_t)(.5 + repeat / (s1 - s0));
00427           
00428 
00429           if( size == first && name != "" )
00430                cout << name << endl;
00431 
00432           if( first != last )
00433           {
00434                // convert int(size_t) to avoid warning on _MSC_VER sys
00435                std::cout << "size = "  << int(size);
00436 
00437                SpeedTestNdigit(size, ndigit, pow10);
00438                while( ndigit < maxSizeDigit )
00439                {    cout << " ";
00440                     ndigit++;
00441                }
00442                cout << " ";
00443           }
00444 
00445           cout << "rate = ";
00446           SpeedTestNdigit(rate, ndigit, pow10);
00447           while( ndigit > 0 )
00448           {
00449                pow10 /= 10;
00450                digit  = rate / pow10;
00451 
00452                // convert int(size_t) to avoid warning on _MSC_VER sys
00453                std::cout << int(digit);
00454 
00455                rate    = rate % pow10;
00456                ndigit -= 1;
00457 
00458                if( (ndigit > 0) && (ndigit % 3 == 0) )
00459                     cout << ",";
00460           }
00461           cout << endl;
00462 
00463           // next size
00464           if( ((int) size) + inc > 0 )
00465                size += inc;
00466           else size  = 0;
00467      }
00468      return;
00469 }
00470 
00471 } // END CppAD namespace
00472 
00473 // END C++
00474 # endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines