CppAD: A C++ Algorithmic Differentiation Package
20130102
|
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