1111#include " src/__support/CPP/string_view.h"
1212#include " src/__support/CPP/type_traits.h"
1313#include " src/__support/FPUtil/FPBits.h"
14+ #include " src/__support/FPUtil/sqrt.h"
1415#include " src/__support/macros/config.h"
1516#include " src/time/clock.h"
1617
@@ -30,40 +31,82 @@ struct BenchmarkOptions {
3031 double scaling_factor = 1.4 ;
3132};
3233
33- struct Measurement {
34+ class RefinableRuntimeEstimator {
3435 uint32_t iterations = 0 ;
35- uint64_t elapsed_cycles = 0 ;
36- };
37-
38- class RefinableRuntimeEstimation {
39- uint64_t total_cycles = 0 ;
40- uint32_t total_iterations = 0 ;
36+ uint64_t sum_of_cycles = 0 ;
37+ uint64_t sum_of_squared_cycles = 0 ;
4138
4239public:
43- uint64_t update (const Measurement &M) {
44- total_cycles += M.elapsed_cycles ;
45- total_iterations += M.iterations ;
46- return total_cycles / total_iterations;
40+ void update (uint64_t cycles) noexcept {
41+ iterations += 1 ;
42+ sum_of_cycles += cycles;
43+ sum_of_squared_cycles += cycles * cycles;
44+ }
45+
46+ double get_mean () const noexcept {
47+ if (iterations == 0 )
48+ return 0.0 ;
49+
50+ return static_cast <double >(sum_of_cycles) / iterations;
51+ }
52+
53+ void update (const RefinableRuntimeEstimator &other) noexcept {
54+ iterations += other.iterations ;
55+ sum_of_cycles += other.sum_of_cycles ;
56+ sum_of_squared_cycles += other.sum_of_squared_cycles ;
57+ }
58+
59+ double get_variance () const noexcept {
60+ if (iterations == 0 )
61+ return 0.0 ;
62+
63+ const double num = static_cast <double >(iterations);
64+ const double sum_x = static_cast <double >(sum_of_cycles);
65+ const double sum_x2 = static_cast <double >(sum_of_squared_cycles);
66+
67+ const double mean_of_squares = sum_x2 / num;
68+ const double mean = sum_x / num;
69+ const double mean_squared = mean * mean;
70+ const double variance = mean_of_squares - mean_squared;
71+
72+ return variance < 0.0 ? 0.0 : variance;
73+ }
74+
75+ double get_stddev () const noexcept {
76+ return fputil::sqrt<double >(get_variance ());
4777 }
78+
79+ uint32_t get_iterations () const noexcept { return iterations; }
4880};
4981
5082// Tracks the progression of the runtime estimation
5183class RuntimeEstimationProgression {
52- RefinableRuntimeEstimation rre;
84+ RefinableRuntimeEstimator estimator;
85+ double current_mean = 0.0 ;
5386
5487public:
55- uint64_t current_estimation = 0 ;
88+ const RefinableRuntimeEstimator &get_estimator () const noexcept {
89+ return estimator;
90+ }
91+
92+ double
93+ compute_improvement (const RefinableRuntimeEstimator &sample_estimator) {
94+ if (sample_estimator.get_iterations () == 0 )
95+ return 1.0 ;
5696
57- double compute_improvement (const Measurement &M) {
58- const uint64_t new_estimation = rre.update (M);
59- double ratio =
60- (static_cast <double >(current_estimation) / new_estimation) - 1.0 ;
97+ estimator.update (sample_estimator);
98+
99+ const double new_mean = estimator.get_mean ();
100+ if (current_mean == 0.0 || new_mean == 0.0 ) {
101+ current_mean = new_mean;
102+ return 1.0 ;
103+ }
61104
62- // Get absolute value
105+ double ratio = (current_mean / new_mean) - 1.0 ;
63106 if (ratio < 0 )
64- ratio * = -1 ;
107+ ratio = -ratio ;
65108
66- current_estimation = new_estimation ;
109+ current_mean = new_mean ;
67110 return ratio;
68111 }
69112};
0 commit comments