File: performance.hpp

package info (click to toggle)
scipy 1.16.0-1exp7
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 234,820 kB
  • sloc: cpp: 503,145; python: 344,611; ansic: 195,638; javascript: 89,566; fortran: 56,210; cs: 3,081; f90: 1,150; sh: 848; makefile: 785; pascal: 284; csh: 135; lisp: 134; xml: 56; perl: 51
file content (119 lines) | stat: -rw-r--r-- 3,196 bytes parent folder | download | duplicates (13)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//  Copyright John Maddock 2015.
//  Use, modification and distribution are subject to the
//  Boost Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#ifndef PERFORMANCE_HPP
#define PERFORMANCE_HPP

#include <boost/math/special_functions/relative_difference.hpp>
#include <boost/array.hpp>
#include <boost/chrono.hpp>
#include <boost/regex.hpp>
#include <iostream>
#include <iomanip>

extern std::vector<std::vector<double> > data;

template <class Array>
void add_data(const Array& a)
{
   //
   // This function is called multiple times to merge multiple data sets into one big table:
   //
   for(typename Array::const_iterator i = a.begin(); i != a.end(); ++i)
   {
      data.push_back(std::vector<double>());
      for(typename Array::value_type::const_iterator j = i->begin(); j != i->end(); ++j)
      {
         data.back().push_back(*j);
      }
   }
}

template <class Func, class Result>
void screen_data(Func f, Result r)
{
   //
   // If any of the implementations being tested produces garbage for one of our
   // test cases (or else if we test a domain they don't support), then we remove that
   // row from the table.  This allows us to only test a common supported sub-set for performance:
   //
   for(std::vector<std::vector<double> >::size_type row = 0; row < data.size(); ++row)
   {
      try
      {
         double computed = f(data[row]);
         double expected = r(data[row]);
         double err = boost::math::relative_difference(computed, expected);
         if(err > 1e-7)
         {
            std::cout << "Erasing row: ";
            for(unsigned i = 0; i < data[row].size(); ++i)
            {
               std::cout << data[row][i] << " ";
            }
            std::cout << "Error was " << err << std::endl;
            data.erase(data.begin() + row);
            --row;
         }
      }
      catch(const std::exception& e)
      {
         std::cout << "Erasing row: ";
         for(unsigned i = 0; i < data[row].size(); ++i)
         {
            std::cout << data[row][i] << " ";
         }
         std::cout << "due to thrown exception: " << e.what() << std::endl;
         data.erase(data.begin() + row);
         --row;
      }
   }
}

template <class Clock>
struct stopwatch
{
   typedef typename Clock::duration duration;
   stopwatch()
   {
      m_start = Clock::now();
   }
   duration elapsed()
   {
      return Clock::now() - m_start;
   }
   void reset()
   {
      m_start = Clock::now();
   }

private:
   typename Clock::time_point m_start;
};

double sum = 0;

template <class Func>
double exec_timed_test(Func f)
{
   double t = 0;
   unsigned repeats = 1;
   do{
      stopwatch<boost::chrono::high_resolution_clock> w;

      for(unsigned count = 0; count < repeats; ++count)
      {
         for(std::vector<std::vector<double> >::const_iterator i = data.begin(); i != data.end(); ++i)
            sum += f(*i);
      }

      t = boost::chrono::duration_cast<boost::chrono::duration<double>>(w.elapsed()).count();
      if(t < 0.5)
         repeats *= 2;
   } while(t < 0.5);
   return t / (repeats * data.size());
}

#endif // PERFORMANCE_HPP