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