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