diff options
| author | Petteri.Aimonen <Petteri.Aimonen@gmail.com> | 2012-02-27 16:40:45 +0000 |
|---|---|---|
| committer | Petteri.Aimonen <Petteri.Aimonen@gmail.com> | 2012-02-27 16:40:45 +0000 |
| commit | 90973e833d69a93525ef2c4eb5ab687ee13342df (patch) | |
| tree | c154fc48cca12a87b8a82f9892c53d593f5da592 /benchmarks/benchmark.c | |
| parent | e929442f7113dd321057293b8addd7b6e781d77f (diff) | |
| download | libfixmath-90973e833d69a93525ef2c4eb5ab687ee13342df.tar.gz | |
Benchmark suite using simulators
Diffstat (limited to 'benchmarks/benchmark.c')
| -rw-r--r-- | benchmarks/benchmark.c | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/benchmarks/benchmark.c b/benchmarks/benchmark.c new file mode 100644 index 0000000..de83388 --- /dev/null +++ b/benchmarks/benchmark.c @@ -0,0 +1,214 @@ +#ifndef NO_FLOAT +#include <math.h> +#endif + +#include <fix16.h> +#include "interface.h" +#include <stdio.h> + +/* Autogenerated testcases */ +#include "testcases.c" + +/* Tools for profiling */ + +typedef struct { + uint32_t min; + uint32_t max; + uint32_t sum; + uint32_t count; +} cyclecount_t; + +// Initializer for cyclecount_t structure. +// Max is initialized to 0 and min is 2^32-1 so that first call to cyclecount_update will set them. +#define CYCLECOUNT_INIT {0xFFFFFFFF, 0, 0, 0} + +// Update cyclecount_t structure after a single measurement has been made. +static void cyclecount_update(cyclecount_t *data, uint32_t cycles) +{ + if (cycles < data->min) + data->min = cycles; + if (cycles > data->max) + data->max = cycles; + + data->sum += cycles; + data->count++; +} + +#define MEASURE(variable, statement) { \ + start_timing(); \ + statement; \ + cyclecount_update(&variable, end_timing()); \ +} + +#define PRINT(variable, label) { \ + print_value(label " min", variable.min); \ + print_value(label " max", variable.max); \ + print_value(label " avg", variable.sum / variable.count); \ +} + +static cyclecount_t exp_cycles = CYCLECOUNT_INIT; +static cyclecount_t sqrt_cycles = CYCLECOUNT_INIT; +static cyclecount_t add_cycles = CYCLECOUNT_INIT; +static cyclecount_t sub_cycles = CYCLECOUNT_INIT; +static cyclecount_t div_cycles = CYCLECOUNT_INIT; +static cyclecount_t mul_cycles = CYCLECOUNT_INIT; + +#ifndef NO_FLOAT +static cyclecount_t float_sqrtf_cycles = CYCLECOUNT_INIT; +static cyclecount_t float_add_cycles = CYCLECOUNT_INIT; +static cyclecount_t float_sub_cycles = CYCLECOUNT_INIT; +static cyclecount_t float_div_cycles = CYCLECOUNT_INIT; +static cyclecount_t float_mul_cycles = CYCLECOUNT_INIT; +#endif + +static fix16_t delta(fix16_t result, fix16_t expected) +{ +#ifdef FIXMATH_NO_OVERFLOW + // Ignore overflow errors when the detection is turned off + if (expected == fix16_min) + return 0; +#endif + + if (result >= expected) + { + return result - expected; + } + else + { + return expected - result; + } +} + +#ifdef FIXMATH_NO_ROUNDING +const fix16_t max_delta = 1; +#else +const fix16_t max_delta = 0; +#endif + +int main() +{ + int i; + interface_init(); + + start_timing(); + print_value("Timestamp bias", end_timing()); + + for (i = 0; i < TESTCASES1_COUNT; i++) + { + fix16_t input = testcases1[i].a; + fix16_t result; + fix16_t expected = testcases1[i].sqrt; + MEASURE(sqrt_cycles, result = fix16_sqrt(input)); + + if (input > 0 && delta(result, expected) > max_delta) + { + print_value("Failed SQRT, i", i); + print_value("Failed SQRT, input", input); + print_value("Failed SQRT, output", result); + print_value("Failed SQRT, expected", expected); + } + + expected = testcases1[i].exp; + MEASURE(exp_cycles, result = fix16_exp(input)); + + if (delta(result, expected) > 400) + { + print_value("Failed EXP, i", i); + print_value("Failed EXP, input", input); + print_value("Failed EXP, output", result); + print_value("Failed EXP, expected", expected); + } + } + PRINT(sqrt_cycles, "fix16_sqrt"); + PRINT(exp_cycles, "fix16_exp"); + + for (i = 0; i < TESTCASES2_COUNT; i++) + { + fix16_t a = testcases2[i].a; + fix16_t b = testcases2[i].b; + volatile fix16_t result; + + fix16_t expected = testcases2[i].add; + MEASURE(add_cycles, result = fix16_add(a, b)); + if (delta(result, expected) > max_delta) + { + print_value("Failed ADD, i", i); + print_value("Failed ADD, a", a); + print_value("Failed ADD, b", b); + print_value("Failed ADD, output", result); + print_value("Failed ADD, expected", expected); + } + + expected = testcases2[i].sub; + MEASURE(sub_cycles, result = fix16_sub(a, b)); + if (delta(result, expected) > max_delta) + { + print_value("Failed SUB, i", i); + print_value("Failed SUB, a", a); + print_value("Failed SUB, b", b); + print_value("Failed SUB, output", result); + print_value("Failed SUB, expected", expected); + } + + expected = testcases2[i].mul; + MEASURE(mul_cycles, result = fix16_mul(a, b)); + if (delta(result, expected) > max_delta) + { + print_value("Failed MUL, i", i); + print_value("Failed MUL, a", a); + print_value("Failed MUL, b", b); + print_value("Failed MUL, output", result); + print_value("Failed MUL, expected", expected); + } + + if (b != 0) + { + expected = testcases2[i].div; + MEASURE(div_cycles, result = fix16_div(a, b)); + if (delta(result, expected) > max_delta) + { + print_value("Failed DIV, i", i); + print_value("Failed DIV, a", a); + print_value("Failed DIV, b", b); + print_value("Failed DIV, output", result); + print_value("Failed DIV, expected", expected); + } + } + } + PRINT(add_cycles, "fix16_add"); + PRINT(sub_cycles, "fix16_sub"); + PRINT(mul_cycles, "fix16_mul"); + PRINT(div_cycles, "fix16_div"); + + /* Compare with floating point performance */ +#ifndef NO_FLOAT + for (i = 0; i < TESTCASES1_COUNT; i++) + { + float input = fix16_to_float(testcases1[i].a); + volatile float result; + MEASURE(float_sqrtf_cycles, result = sqrtf(input)); + } + PRINT(float_sqrtf_cycles, "float sqrtf"); + + for (i = 0; i < TESTCASES2_COUNT; i++) + { + float a = fix16_to_float(testcases2[i].a); + float b = fix16_to_float(testcases2[i].b); + volatile float result; + MEASURE(float_add_cycles, result = a + b); + MEASURE(float_sub_cycles, result = a - b); + MEASURE(float_mul_cycles, result = a * b); + + if (b != 0) + { + MEASURE(float_div_cycles, result = a / b); + } + } + PRINT(float_add_cycles, "float add"); + PRINT(float_sub_cycles, "float sub"); + PRINT(float_mul_cycles, "float mul"); + PRINT(float_div_cycles, "float div"); +#endif + + return 0; +} |
