CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
speed_test.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_UTILITY_SPEED_TEST_HPP
2 # define CPPAD_UTILITY_SPEED_TEST_HPP
3 
4 /* --------------------------------------------------------------------------
5 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
6 
7 CppAD is distributed under multiple licenses. This distribution is under
8 the terms of the
9  Eclipse Public License Version 1.0.
10 
11 A copy of this license is included in the COPYING file of this distribution.
12 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
13 -------------------------------------------------------------------------- */
14 
15 /*
16 $begin speed_test$$
17 $spell
18  gettimeofday
19  vec
20  cppad.hpp
21  Microsoft
22  namespace
23  std
24  const
25  cout
26  ctime
27  ifdef
28  const
29  endif
30  cpp
31 $$
32 
33 
34 $section Run One Speed Test and Return Results$$
35 $mindex speed_test$$
36 
37 $head Syntax$$
38 $codei%# include <cppad/utility/speed_test.hpp>
39 %$$
40 $icode%rate_vec% = speed_test(%test%, %size_vec%, %time_min%)%$$
41 
42 $head Purpose$$
43 The $code speed_test$$ function executes a speed test
44 for various sized problems
45 and reports the rate of execution.
46 
47 $head Motivation$$
48 It is important to separate small calculation units
49 and test them individually.
50 This way individual changes can be tested in the context of the
51 routine that they are in.
52 On many machines, accurate timing of a very short execution
53 sequences is not possible.
54 In addition,
55 there may be set up and tear down time for a test that
56 we do not really want included in the timing.
57 For this reason $code speed_test$$
58 automatically determines how many times to
59 repeat the section of the test that we wish to time.
60 
61 
62 $head Include$$
63 The file $code cppad/speed_test.hpp$$ defines the
64 $code speed_test$$ function.
65 This file is included by $code cppad/cppad.hpp$$
66 and it can also be included separately with out the rest of
67 the $code CppAD$$ routines.
68 
69 $head Vector$$
70 We use $icode Vector$$ to denote a
71 $cref/simple vector class/SimpleVector/$$ with elements
72 of type $code size_t$$.
73 
74 $head test$$
75 The $code speed_test$$ argument $icode test$$ is a function with the syntax
76 $codei%
77  %test%(%size%, %repeat%)
78 %$$
79 and its return value is $code void$$.
80 
81 $subhead size$$
82 The $icode test$$ argument $icode size$$ has prototype
83 $codei%
84  size_t %size%
85 %$$
86 It specifies the size for this test.
87 
88 $subhead repeat$$
89 The $icode test$$ argument $icode repeat$$ has prototype
90 $codei%
91  size_t %repeat%
92 %$$
93 It specifies the number of times to repeat the test.
94 
95 $head size_vec$$
96 The $code speed_test$$ argument $icode size_vec$$ has prototype
97 $codei%
98  const %Vector%& %size_vec%
99 %$$
100 This vector determines the size for each of the tests problems.
101 
102 $head time_min$$
103 The argument $icode time_min$$ has prototype
104 $codei%
105  double %time_min%
106 %$$
107 It specifies the minimum amount of time in seconds
108 that the $icode test$$ routine should take.
109 The $icode repeat$$ argument to $icode test$$ is increased
110 until this amount of execution time is reached.
111 
112 $head rate_vec$$
113 The return value $icode rate_vec$$ has prototype
114 $codei%
115  %Vector%& %rate_vec%
116 %$$
117 We use $latex n$$ to denote its size which is the same as
118 the vector $icode size_vec$$.
119 For $latex i = 0 , \ldots , n-1$$,
120 $codei%
121  %rate_vec%[%i%]
122 %$$
123 is the ratio of $icode repeat$$ divided by time in seconds
124 for the problem with size $icode%size_vec%[%i%]%$$.
125 
126 $head Timing$$
127 If your system supports the unix $code gettimeofday$$ function,
128 it will be used to measure time.
129 Otherwise,
130 time is measured by the difference in
131 $codep
132  (double) clock() / (double) CLOCKS_PER_SEC
133 $$
134 in the context of the standard $code <ctime>$$ definitions.
135 
136 $children%
137  speed/example/speed_test.cpp
138 %$$
139 $head Example$$
140 The routine $cref speed_test.cpp$$ is an example and test
141 of $code speed_test$$.
142 
143 $end
144 -----------------------------------------------------------------------
145 */
146 
147 # include <cstddef>
148 # include <cmath>
149 
152 
153 
154 namespace CppAD { // BEGIN CppAD namespace
155 
156 // implemented as an inline so that can include in multiple link modules
157 // with this same file
158 template <class Vector>
159 inline Vector speed_test(
160  void test(size_t size, size_t repeat),
161  const Vector& size_vec ,
162  double time_min )
163 {
164  // check that size_vec is a simple vector with size_t elements
165  CheckSimpleVector<size_t, Vector>();
166 
167  size_t n = size_vec.size();
168  Vector rate_vec(n);
169  size_t i;
170  for(i = 0; i < n; i++)
171  { size_t size = size_vec[i];
172  size_t repeat = 1;
173  double s0 = elapsed_seconds();
174  double s1 = elapsed_seconds();
175  while( s1 - s0 < time_min )
176  { repeat = 2 * repeat;
177  s0 = elapsed_seconds();
178  test(size, repeat);
179  s1 = elapsed_seconds();
180  }
181  double rate = .5 + double(repeat) / (s1 - s0);
182  // first convert to float to avoid warning with g++ -Wconversion
183  rate_vec[i] = static_cast<size_t>( static_cast<float>(rate) );
184  }
185  return rate_vec;
186 }
187 
188 } // END CppAD namespace
189 
190 /*
191 $begin SpeedTest$$
192 $spell
193  cppad.hpp
194  Microsoft
195  namespace
196  std
197  const
198  cout
199  ctime
200  ifdef
201  const
202  endif
203  cpp
204 $$
205 
206 
207 $section Run One Speed Test and Print Results$$
208 $mindex SpeedTest$$
209 
210 $head Syntax$$
211 
212 $codei%# include <cppad/utility/speed_test.hpp>
213 %$$
214 $codei%SpeedTest(%Test%, %first%, %inc%, %last%)%$$
215 
216 
217 $head Purpose$$
218 The $code SpeedTest$$ function executes a speed test
219 for various sized problems
220 and reports the results on standard output; i.e. $code std::cout$$.
221 The size of each test problem is included in its report
222 (unless $icode first$$ is equal to $icode last$$).
223 
224 $head Motivation$$
225 It is important to separate small calculation units
226 and test them individually.
227 This way individual changes can be tested in the context of the
228 routine that they are in.
229 On many machines, accurate timing of a very short execution
230 sequences is not possible.
231 In addition,
232 there may be set up time for a test that
233 we do not really want included in the timing.
234 For this reason $code SpeedTest$$
235 automatically determines how many times to
236 repeat the section of the test that we wish to time.
237 
238 
239 $head Include$$
240 The file $code speed_test.hpp$$ contains the
241 $code SpeedTest$$ function.
242 This file is included by $code cppad/cppad.hpp$$
243 but it can also be included separately with out the rest of
244 the $code CppAD$$ routines.
245 
246 $head Test$$
247 The $code SpeedTest$$ argument $icode Test$$ is a function with the syntax
248 $codei%
249  %name% = %Test%(%size%, %repeat%)
250 %$$
251 
252 $subhead size$$
253 The $icode Test$$ argument $icode size$$ has prototype
254 $codei%
255  size_t %size%
256 %$$
257 It specifies the size for this test.
258 
259 $subhead repeat$$
260 The $icode Test$$ argument $icode repeat$$ has prototype
261 $codei%
262  size_t %repeat%
263 %$$
264 It specifies the number of times to repeat the test.
265 
266 $subhead name$$
267 The $icode Test$$ result $icode name$$ has prototype
268 $codei%
269  std::string %name%
270 %$$
271 The results for this test are reported on $code std::cout$$
272 with $icode name$$ as an identifier for the test.
273 It is assumed that,
274 for the duration of this call to $code SpeedTest$$,
275 $icode Test$$ will always return
276 the same value for $icode name$$.
277 If $icode name$$ is the empty string,
278 no test name is reported by $code SpeedTest$$.
279 
280 $head first$$
281 The $code SpeedTest$$ argument $icode first$$ has prototype
282 $codei%
283  size_t %first%
284 %$$
285 It specifies the size of the first test problem reported by this call to
286 $code SpeedTest$$.
287 
288 $head last$$
289 The $code SpeedTest$$ argument $icode last$$ has prototype
290 $codei%
291  size_t %last%
292 %$$
293 It specifies the size of the last test problem reported by this call to
294 $code SpeedTest$$.
295 
296 $head inc$$
297 The $code SpeedTest$$ argument $icode inc$$ has prototype
298 $codei%
299  int %inc%
300 %$$
301 It specifies the increment between problem sizes; i.e.,
302 all values of $icode size$$ in calls to $icode Test$$ are given by
303 $codei%
304  %size% = %first% + %j% * %inc%
305 %$$
306 where $icode j$$ is a positive integer.
307 The increment can be positive or negative but it cannot be zero.
308 The values $icode first$$, $icode last$$ and $icode inc$$ must
309 satisfy the relation
310 $latex \[
311  inc * ( last - first ) \geq 0
312 \] $$
313 
314 $head rate$$
315 The value displayed in the $code rate$$ column on $code std::cout$$
316 is defined as the value of $icode repeat$$ divided by the
317 corresponding elapsed execution time in seconds.
318 The elapsed execution time is measured by the difference in
319 $codep
320  (double) clock() / (double) CLOCKS_PER_SEC
321 $$
322 in the context of the standard $code <ctime>$$ definitions.
323 
324 
325 $head Errors$$
326 If one of the restrictions above is violated,
327 the CppAD error handler is used to report the error.
328 You can redefine this action using the instructions in
329 $cref ErrorHandler$$
330 
331 $head Example$$
332 $children%
333  speed/example/speed_program.cpp
334 %$$
335 The program $cref speed_program.cpp$$ is an example usage
336 of $code SpeedTest$$.
337 
338 $end
339 -----------------------------------------------------------------------
340 */
341 // BEGIN C++
342 
343 
344 # include <string>
345 # include <iostream>
346 # include <iomanip>
347 # include <cppad/core/cppad_assert.hpp>
348 
349 namespace CppAD { // BEGIN CppAD namespace
350 
351 inline void SpeedTestNdigit(size_t value, size_t &ndigit, size_t &pow10)
352 { pow10 = 10;
353  ndigit = 1;
354  while( pow10 <= value )
355  { pow10 *= 10;
356  ndigit += 1;
357  }
358 }
359 
360 // implemented as an inline so that can include in multiple link modules
361 // with this same file
362 inline void SpeedTest(
363  std::string Test(size_t size, size_t repeat),
364  size_t first,
365  int inc,
366  size_t last
367 )
368 {
369 
370  using std::cout;
371  using std::endl;
372 
373  size_t size;
374  size_t repeat;
375  size_t rate;
376  size_t digit;
377  size_t ndigit;
378  size_t pow10;
379  size_t maxSize;
380  size_t maxSizeDigit;
381 
382  double s0;
383  double s1;
384 
385  std::string name;
386 
388  inc != 0 && first != 0 && last != 0,
389  "inc, first, or last is zero in call to SpeedTest"
390  );
392  (inc > 0 && first <= last) || (inc < 0 && first >= last),
393  "SpeedTest: increment is positive and first > last or "
394  "increment is negative and first < last"
395  );
396 
397  // compute maxSize
398  maxSize = size = first;
399  while( (inc > 0 && size <= last) || (inc < 0 && size >= last) )
400  {
401  if( size > maxSize )
402  maxSize = size;
403 
404  // next size
405  if( ((int) size) + inc > 0 )
406  size += inc;
407  else size = 0;
408  }
409  SpeedTestNdigit(maxSize, maxSizeDigit, pow10);
410 
411  size = first;
412  while( (inc > 0 && size <= last) || (inc < 0 && size >= last) )
413  {
414  repeat = 1;
415  s0 = elapsed_seconds();
416  s1 = elapsed_seconds();
417  while( s1 - s0 < 1. )
418  { repeat = 2 * repeat;
419  s0 = elapsed_seconds();
420  name = Test(size, repeat);
421  s1 = elapsed_seconds();
422  }
423  double r = .5 + double(repeat) / (s1 - s0);
424  // first convert to float to avoid warning with g++ -Wconversion
425  rate = static_cast<size_t>( static_cast<float>( r ) );
426 
427  if( size == first && name != "" )
428  cout << name << endl;
429 
430  if( first != last )
431  {
432  // convert int(size_t) to avoid warning on _MSC_VER sys
433  std::cout << "size = " << int(size);
434 
435  SpeedTestNdigit(size, ndigit, pow10);
436  while( ndigit < maxSizeDigit )
437  { cout << " ";
438  ndigit++;
439  }
440  cout << " ";
441  }
442 
443  cout << "rate = ";
444  SpeedTestNdigit(rate, ndigit, pow10);
445  while( ndigit > 0 )
446  {
447  pow10 /= 10;
448  digit = rate / pow10;
449 
450  // convert int(size_t) to avoid warning on _MSC_VER sys
451  std::cout << int(digit);
452 
453  rate = rate % pow10;
454  ndigit -= 1;
455 
456  if( (ndigit > 0) && (ndigit % 3 == 0) )
457  cout << ",";
458  }
459  cout << endl;
460 
461  // next size
462  if( ((int) size) + inc > 0 )
463  size += inc;
464  else size = 0;
465  }
466  return;
467 }
468 
469 } // END CppAD namespace
470 
471 // END C++
472 # endif
#define CPPAD_ASSERT_KNOWN(exp, msg)
Check that exp is true, if not print msg and terminate execution.
Vector speed_test(void test(size_t size, size_t repeat), const Vector &size_vec, double time_min)
Definition: speed_test.hpp:159
Define the CppAD error checking macros (all of which begin with CPPAD_ASSERT_)
Function that returns the elapsed seconds from first call.
void SpeedTest(std::string Test(size_t size, size_t repeat), size_t first, int inc, size_t last)
Definition: speed_test.hpp:362
void SpeedTestNdigit(size_t value, size_t &ndigit, size_t &pow10)
Definition: speed_test.hpp:351
double elapsed_seconds(void)
Returns the elapsed number since the first call to this function.