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