diff --git a/inc/fixture.h b/inc/fixture.h index e86a5bd..fa7ba0e 100644 --- a/inc/fixture.h +++ b/inc/fixture.h @@ -1,5 +1,14 @@ +// chunck_size is the size of the data to be provided to the tested function extern const size_t chunk_size; +// number_measurements allows to set the number of measurements per pass, +// note that currently the report awaits enough_measurements = 10000 measurements. extern const size_t number_measurements; +// do_one_computation would typically be one or more passes of the functions +// you're timing using the input in range chunk_size pointed by data extern uint8_t do_one_computation(uint8_t *data); +// init_dut provides a mean to perform some initializations at startup extern void init_dut(void); +// prepare_inputs allows one to provide the input data. Dudect will try +// and find discrepancies between the distributions of the data +// labelled in class 0 and class 1. extern void prepare_inputs(uint8_t *input_data, uint8_t *classes); diff --git a/inc/ttest.h b/inc/ttest.h index e6722a0..006871d 100644 --- a/inc/ttest.h +++ b/inc/ttest.h @@ -1,6 +1,6 @@ typedef struct { double mean[2]; - double m2[2]; + double m2[2]; // m2, once divided by n-1 provides the sample variance double n[2]; } t_ctx; diff --git a/src/fixture.c b/src/fixture.c index 39ae500..cdac802 100644 --- a/src/fixture.c +++ b/src/fixture.c @@ -65,12 +65,21 @@ static void prepare_percentiles(int64_t *ticks) { } } -static void measure(int64_t *ticks, uint8_t *input_data) { +static void measure(int64_t *exec_times, uint8_t *input_data) { + int64_t *ticks = calloc(number_measurements + 1, sizeof(int64_t)); + if (!ticks) { + die(); + } + for (size_t i = 0; i < number_measurements; i++) { ticks[i] = cpucycles(); do_one_computation(input_data + i * chunk_size); } ticks[number_measurements] = cpucycles(); + + differentiate(exec_times, ticks); // inplace + + free(ticks); } static void differentiate(int64_t *exec_times, int64_t *ticks) { @@ -195,19 +204,17 @@ static void report(void) { static void doit(void) { // XXX move these callocs to parent - int64_t *ticks = calloc(number_measurements + 1, sizeof(int64_t)); int64_t *exec_times = calloc(number_measurements, sizeof(int64_t)); uint8_t *classes = calloc(number_measurements, sizeof(uint8_t)); uint8_t *input_data = calloc(number_measurements * chunk_size, sizeof(uint8_t)); - if (!ticks || !exec_times || !classes || !input_data) { + if ( !exec_times || !classes || !input_data) { die(); } prepare_inputs(input_data, classes); - measure(ticks, input_data); - differentiate(exec_times, ticks); // inplace + measure(exec_times, input_data); // we compute the percentiles only if they are not filled yet if (percentiles[number_percentiles - 1] == 0) { @@ -216,7 +223,6 @@ static void doit(void) { update_statistics(exec_times, classes); report(); - free(ticks); free(exec_times); free(classes); free(input_data); diff --git a/src/ttest.c b/src/ttest.c index 430384c..ea5132f 100644 --- a/src/ttest.c +++ b/src/ttest.c @@ -24,11 +24,13 @@ void t_push(t_ctx *ctx, double x, uint8_t class) { // see Knuth Vol 2 double delta = x - ctx->mean[class]; ctx->mean[class] = ctx->mean[class] + delta / ctx->n[class]; + // note this is not yet unbiased ctx->m2[class] = ctx->m2[class] + delta * (x - ctx->mean[class]); } double t_compute(t_ctx *ctx) { double var[2] = {0.0, 0.0}; + // to obtain the sample variance, we unbias: var[0] = ctx->m2[0] / (ctx->n[0] - 1); var[1] = ctx->m2[1] / (ctx->n[1] - 1); double num = (ctx->mean[0] - ctx->mean[1]);