FFmpeg
stats.h
Go to the documentation of this file.
1 /*
2  * Copyright © 2025, Niklas Haas
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #ifndef CHECKASM_STATS_H
28 #define CHECKASM_STATS_H
29 
30 #include <assert.h>
31 #include <math.h>
32 #include <stdint.h>
33 #include <string.h>
34 
35 typedef struct CheckasmVar {
36  double lmean, lvar; /* log mean and variance */
37 } CheckasmVar;
38 
39 /* Sample the PDF of a random variable at the given quantile */
40 static inline double checkasm_sample(const CheckasmVar x, const double q)
41 {
42  return exp(x.lmean + q * sqrt(x.lvar));
43 }
44 
45 static inline double checkasm_median(const CheckasmVar x)
46 {
47  return exp(x.lmean);
48 }
49 
50 static inline double checkasm_mode(const CheckasmVar x)
51 {
52  return exp(x.lmean - x.lvar);
53 }
54 
55 static inline double checkasm_mean(const CheckasmVar x)
56 {
57  return exp(x.lmean + 0.5 * x.lvar);
58 }
59 
60 static inline double checkasm_stddev(const CheckasmVar x)
61 {
62  return exp(x.lmean + 0.5 * x.lvar) * sqrt(exp(x.lvar) - 1.0);
63 }
64 
65 static inline CheckasmVar checkasm_var_const(double x)
66 {
67  return (CheckasmVar) { log(x), 0.0 };
68 }
69 
70 /* Assumes independent random variables */
78 
79 /* Statistical analysis helpers */
80 typedef struct CheckasmSample {
81  uint64_t sum; /* batched sum of data points */
82  int count; /* number of data points in batch */
84 
85 typedef struct CheckasmStats {
86  /* With a ~12% exponential growth on the number of data points per sample,
87  * 256 samples can effectively represent many billions of data points */
88 #define CHECKASM_STATS_SAMPLES 256
93 
94 static inline void checkasm_stats_reset(CheckasmStats *const stats)
95 {
96  stats->nb_samples = 0;
97  stats->next_count = 1;
98 }
99 
100 static inline void checkasm_stats_add(CheckasmStats *const stats, const CheckasmSample s)
101 {
102  if (s.sum > 0 && s.count > 0) {
104  stats->samples[stats->nb_samples++] = s;
105  }
106 }
107 
108 static inline void checkasm_stats_count_grow(CheckasmStats *const stats, uint64_t cycles,
109  uint64_t target_cycles)
110 {
111  if (cycles < target_cycles >> 10) { /* sum[(1+1/64)^n | n < 200] */
112  /* Function is very fast, increase iteration count dramatically */
113  stats->next_count <<= 1;
114  } else if (stats->next_count < 1 << 25) {
115  /* Grow more slowly at 1/64 = ~1.5% growth */
116  stats->next_count = ((stats->next_count << 6) + stats->next_count + 63) >> 6;
117  }
118 }
119 
121 
122 typedef struct CheckasmMeasurement {
125  CheckasmStats stats; /* last measurement run */
127 
128 static inline void checkasm_measurement_init(CheckasmMeasurement *measurement)
129 {
130  measurement->product = checkasm_var_const(1.0);
131  measurement->nb_measurements = 0;
132  measurement->stats.nb_samples = 0;
133 }
134 
135 static inline void checkasm_measurement_update(CheckasmMeasurement *measurement,
136  const CheckasmStats stats)
137 {
139  measurement->product = checkasm_var_mul(measurement->product, est);
140  measurement->nb_measurements++;
141  measurement->stats.nb_samples = stats.nb_samples;
142  memcpy(measurement->stats.samples, stats.samples,
143  sizeof(stats.samples[0]) * stats.nb_samples);
144 }
145 
146 static inline CheckasmVar
148 {
149  return checkasm_var_pow(measurement.product, 1.0 / measurement.nb_measurements);
150 }
151 
152 #endif /* CHECKASM_STATS_H */
CheckasmStats::next_count
int next_count
Definition: stats.h:91
CheckasmStats::samples
CheckasmSample samples[CHECKASM_STATS_SAMPLES]
Definition: stats.h:89
normalize.log
log
Definition: normalize.py:21
checkasm_var_inv
CheckasmVar checkasm_var_inv(CheckasmVar a)
Definition: stats.c:86
CheckasmMeasurement::stats
CheckasmStats stats
Definition: stats.h:125
b
#define b
Definition: input.c:43
CheckasmMeasurement::nb_measurements
int nb_measurements
Definition: stats.h:124
CHECKASM_STATS_SAMPLES
#define CHECKASM_STATS_SAMPLES
Definition: stats.h:88
checkasm_var_add
CheckasmVar checkasm_var_add(CheckasmVar a, CheckasmVar b)
Definition: stats.c:49
checkasm_measurement_result
static CheckasmVar checkasm_measurement_result(const CheckasmMeasurement measurement)
Definition: stats.h:147
checkasm_mode
static double checkasm_mode(const CheckasmVar x)
Definition: stats.h:50
target_cycles
uint64_t target_cycles
Definition: checkasm.c:117
s
#define s(width, name)
Definition: cbs_vp9.c:198
checkasm_mean
static double checkasm_mean(const CheckasmVar x)
Definition: stats.h:55
checkasm_var_const
static CheckasmVar checkasm_var_const(double x)
Definition: stats.h:65
cycles
uint64_t cycles
Definition: checkasm.c:94
CheckasmSample::sum
uint64_t sum
Definition: stats.h:81
CheckasmSample::count
int count
Definition: stats.h:82
checkasm_var_sub
CheckasmVar checkasm_var_sub(CheckasmVar a, CheckasmVar b)
Definition: stats.c:64
exp
int8_t exp
Definition: eval.c:76
checkasm_stats_estimate
CheckasmVar checkasm_stats_estimate(const CheckasmStats *stats)
Definition: stats.c:102
checkasm_measurement_init
static void checkasm_measurement_init(CheckasmMeasurement *measurement)
Definition: stats.h:128
CheckasmMeasurement::product
CheckasmVar product
Definition: stats.h:123
stats
static CheckasmStats stats
Definition: checkasm.c:75
checkasm_var_div
CheckasmVar checkasm_var_div(CheckasmVar a, CheckasmVar b)
Definition: stats.c:94
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
CheckasmMeasurement
Definition: stats.h:122
checkasm_median
static double checkasm_median(const CheckasmVar x)
Definition: stats.h:45
checkasm_var_pow
CheckasmVar checkasm_var_pow(CheckasmVar a, double exp)
Definition: stats.c:41
checkasm_stats_count_grow
static void checkasm_stats_count_grow(CheckasmStats *const stats, uint64_t cycles, uint64_t target_cycles)
Definition: stats.h:108
checkasm_stddev
static double checkasm_stddev(const CheckasmVar x)
Definition: stats.h:60
CheckasmVar::lmean
double lmean
Definition: stats.h:36
CheckasmVar
Definition: stats.h:35
CheckasmSample
Definition: stats.h:80
checkasm_stats_reset
static void checkasm_stats_reset(CheckasmStats *const stats)
Definition: stats.h:94
checkasm_var_mul
CheckasmVar checkasm_var_mul(CheckasmVar a, CheckasmVar b)
Definition: stats.c:78
CheckasmStats::nb_samples
int nb_samples
Definition: stats.h:90
CheckasmStats
Definition: stats.h:85
checkasm_measurement_update
static void checkasm_measurement_update(CheckasmMeasurement *measurement, const CheckasmStats stats)
Definition: stats.h:135
CheckasmVar::lvar
double lvar
Definition: stats.h:36
checkasm_sample
static double checkasm_sample(const CheckasmVar x, const double q)
Definition: stats.h:40
checkasm_stats_add
static void checkasm_stats_add(CheckasmStats *const stats, const CheckasmSample s)
Definition: stats.h:100
checkasm_var_scale
CheckasmVar checkasm_var_scale(CheckasmVar a, double s)
Definition: stats.c:32