From 4d3a7eb1bf238b5f7abeca8efd09e35254bba1a0 Mon Sep 17 00:00:00 2001 From: Jasper Date: Wed, 3 Sep 2025 14:51:47 +0200 Subject: More work on benchmarking, simplified 1st version The performance of functions (with one or two matrix arguments) can now be benchmarked. To time and analyse most functions, the user does not have to handle the memory or pass matrices. Just provide the dimensions, function name, (optional) string with details, and missing arguments to the function. --- debug.c | 155 ++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 83 insertions(+), 72 deletions(-) diff --git a/debug.c b/debug.c index e37f740..0dbc2b9 100644 --- a/debug.c +++ b/debug.c @@ -12,96 +12,107 @@ if (tmp < 0) str = NULL; \ } while (0) -#define TIMER(func, details, samples, ...) \ - do { \ - size_t _samples = (samples); \ - clock_t _t; \ - double _xs[_samples]; \ - for (size_t _i = 0; _i < _samples; ++_i) \ - { \ - _t = clock(); \ - (__VA_ARGS__); \ - _xs[_i] = ((double) (clock() - _t)) / CLOCKS_PER_SEC; \ - } \ - double max = _xs[0], min = _xs[0], sum = 0; \ - \ - for (size_t i = 0; i < _samples; ++i) \ - { \ - if (_xs[i] > max) max = _xs[i]; \ - else if (_xs[i] < min) min = _xs[i]; \ - sum += _xs[i]; \ - } \ - printf("BENCHMARK (CPU time in s)\n"); \ - printf("---------------------\n"); \ - printf("Function : %s\n", (func)); \ - if ((details)[0] != '\0') \ - printf("Details : %s\n", (details)); \ - printf("Total (%ld samples) : %f\n", _samples, sum); \ - printf("Avg. : %f\n", sum / _samples); \ - printf("Max : %f\n", max); \ - printf("Min : %f\n", min); \ +#define TIMER(_dt, ...) \ + do { \ + clock_t _t; \ + _t = clock(); \ + (__VA_ARGS__); \ + *_dt = ((double) (clock() - _t)) / CLOCKS_PER_SEC; \ } while (0) -#define BENCHMARK_RAND1(m, n, bound_l, bound_u, func,...) \ - do { \ - Matrix *A = matrix_rand((m), (n), (bound_l), (bound_u), MATRIX_NONE); \ - func(A, ##__VA_ARGS__); \ - free(A); \ +#define MATRIX_BM_BOUND_L 0 +#define MATRIX_BM_BOUND_U 100 +#define MATRIX_BM_N_SAMPLES 100 +#define MATRIX_BM_TYPE MATRIX_NONE + +#define BENCHMARK_RAND1(m, n, func, details_str, ...) \ + do { \ + double _samples[MATRIX_BM_N_SAMPLES]; \ + for (int i = 0; i < MATRIX_BM_N_SAMPLES; ++i) \ + { \ + Matrix *_A = matrix_rand((m), (n), MATRIX_BM_BOUND_L, MATRIX_BM_BOUND_U, MATRIX_BM_TYPE); \ + TIMER(&_samples[i], \ + func(_A, ##__VA_ARGS__) \ + ); \ + matrix_free(_A); \ + } \ + print_bm(#func, (details_str), _samples, MATRIX_BM_N_SAMPLES); \ } while(0) +#define BENCHMARK_RAND2(m1, n1, m2, n2, func, details_str, ...) \ + do { \ + double _samples[MATRIX_BM_N_SAMPLES]; \ + for (int i = 0; i < MATRIX_BM_N_SAMPLES; ++i) \ + { \ + Matrix *_A = matrix_rand((m1), (n1), MATRIX_BM_BOUND_L, MATRIX_BM_BOUND_U, MATRIX_BM_TYPE); \ + Matrix *_B = matrix_rand((m2), (n2), MATRIX_BM_BOUND_L, MATRIX_BM_BOUND_U, MATRIX_BM_TYPE); \ + TIMER(&_samples[i], \ + func(_A, _B, ##__VA_ARGS__) \ + ); \ + matrix_free(_A); \ + matrix_free(_B); \ + } \ + print_bm(#func, (details_str), _samples, MATRIX_BM_N_SAMPLES); \ + } while(0) + +void print_bm(char *func_str, char *details_str, double samples[], size_t n_samples) +{ + double max = samples[0], min = samples[0], sum = 0; + + for (size_t i = 0; i < n_samples; ++i) + { + if (samples[i] > max) max = samples[i]; + else if (samples[i] < min) min = samples[i]; + sum += samples[i]; + } + printf("BENCHMARK (CPU time in s)\n"); + printf("---------------------\n"); + printf("Function : %s\n", func_str); + if (details_str[0] != '\0') + printf("Details : %s\n", details_str); + printf("Total (%ld samples) : %f\n", n_samples, sum); + printf("Avg. : %f\n", sum / n_samples); + printf("Max : %f\n", max); + printf("Min : %f\n", min); +} + int main() { srand(time(NULL)); /* run_tests() */ - /* TODO: Add timing. For now the macro executes the given function once */ - BENCHMARK_RAND1( - 100, 100, /* Dimensions: m x n */ - 0, 100, /* Value bounds */ - matrix_swap1, /* Function to be tested */ - MATRIX_SWAP_ROWS, 0, 1 /* List of arguments to function */ - ); - - Matrix *A, *B; int n = 100; - size_t samples = 500; - char *str; - STR_FMT(str, "rows, %dx%d random matrices", n, n); - - TIMER("swap()", str, samples, - A = matrix_rand(n, n, 0, 100, MATRIX_NONE), - matrix_swap(A, MATRIX_SWAP_ROWS, 0, 1), - matrix_free(A) - ); + BENCHMARK_RAND1( + n, n, + matrix_swap, + "rows", + MATRIX_SWAP_ROWS, 0, 1 + ); printf("\n"); - TIMER("swap1()", str, samples, - A = matrix_rand(n, n, 0, 100, MATRIX_NONE), - matrix_swap1(A, MATRIX_SWAP_ROWS, 0, 1), - matrix_free(A) - ); + BENCHMARK_RAND1( + n, n, + matrix_swap1, + "rows", + MATRIX_SWAP_ROWS, 0, 1 + ); printf("\n"); - TIMER("matrix_eq()", "", samples, - A = matrix_rand(n, n, 0, 100, MATRIX_NONE), - B = matrix_rand(n, n, 0, 100, MATRIX_NONE), - matrix_eq(A, B, 0.01), - matrix_free(A), - matrix_free(B) - ); + BENCHMARK_RAND2( + n, n, n, n, + matrix_eq, + "", + 0.01 + ); printf("\n"); - TIMER("matrix_add()", "", samples, - A = matrix_rand(n, n, 0, 100, MATRIX_NONE), - B = matrix_rand(n, n, 0, 100, MATRIX_NONE), - matrix_add(A, B), - matrix_free(A), - matrix_free(B) - ); - - free(str); + BENCHMARK_RAND2( + n, n, n, n, + matrix_add, + "" + ); } -- cgit v1.2.3