From 65765763aed5364f4054382834ce98e2a34d57c7 Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Sat, 7 Dec 2019 11:58:19 +0100 Subject: [PATCH] * Add generic parser for bench. * Factorization --- bench/common.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++ bench/common.h | 93 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 163 insertions(+), 27 deletions(-) diff --git a/bench/common.c b/bench/common.c index 31ade56e..2ad1268f 100644 --- a/bench/common.c +++ b/bench/common.c @@ -23,6 +23,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include "common.h" void compiler_barrier(void *p) @@ -32,3 +33,99 @@ void compiler_barrier(void *p) // Can be used for FLTO building // asm volatile("": "+r" (p) : :"memory"); } + +struct parse_opt_s { + int test_function; + double from, to, step, grow; + bool graph; +}; + +static void +parse_config(struct parse_opt_s *opt, int argc, const char *argv[]) +{ + char *end; + + opt->test_function = 0; + opt->from = 0.0; + opt->to = 0.0; + opt->step = 0.0; + opt->grow = 1.1; + opt->graph = false; + + for(int i = 1; i < argc ; i++) + { + if (argv[i][0] == '-') { + if (strcmp(argv[i], "--from") == 0){ + i++; + opt->from = strtod(argv[i], &end); + opt->to = opt->from; + } else if (strcmp(argv[i], "--to") == 0) { + i++; + opt->to = strtod(argv[i], &end); + opt->grow = 1.1; + } else if (strcmp(argv[i], "--step") == 0) { + i++; + opt->step = strtod(argv[i], &end); + opt->grow = 0; + } else if (strcmp(argv[i], "--grow") == 0) { + i++; + opt->grow = strtod(argv[i], &end); + opt->step = 0; + } else if (strcmp(argv[i], "--graph") == 0) { + opt->graph = true; + } else { + fprintf(stderr, "ERROR: Option unkown: %s.\n", + argv[i]); + exit(-1); + } + if (*end != 0) { + fprintf(stderr, "ERROR: Cannot parse %s. Expected float\n", + argv[i]); + exit(-1); + } + + } else { + opt->test_function = strtol (argv[i], &end, 10); + if (*end != 0) { + fprintf(stderr, "ERROR: Cannot parse %s. Expected integer\n", + argv[i]); + exit(-1); + } + } + } +} + +static int +select_config(int func, size_t n, const config_func_t functions[]) +{ + for(size_t i = 0; i < n;i++) { + if (functions[i].num == func) + return i; + } + fprintf(stderr, "ERROR: Function number %d not found\n", func); + exit(-1); +} + +void +test(size_t n, const config_func_t functions[], int argc, const char *argv[]) +{ + // options + // NUMBER + // --from NUMBER --to NUMBER --step NUMBER --grow NUMBER + // --graph + struct parse_opt_s arg; + parse_config(&arg, argc, argv); + int i = select_config(arg.test_function, n, functions); + double from = arg.from == 0 ? functions[i].default_n : arg.from; + double to = arg.from == 0 ? functions[i].default_n : arg.to; + // Do the bench + for(double n = from; n <= to ; n = (arg.grow == 0 ? n + arg.step : n * arg.grow)) + { + if (functions[i].init != NULL) + functions[i].init(n); + test_function(functions[i].funcname, (size_t) n, functions[i].func); + if (functions[i].clear != NULL) + functions[i].clear(); + } + return; +} diff --git a/bench/common.h b/bench/common.h index 0d96ea70..0e377950 100644 --- a/bench/common.h +++ b/bench/common.h @@ -27,36 +27,57 @@ #include #include +#include + +// Needed for M_THREAD_ATTR +#if defined(MULTI_THREAD_MEASURE) +#include "m-mutex.h" +#endif #if defined(_WIN32) -/* WINDOWS variant */ -#include +# include +#elif (defined(__APPLE__) && defined(__MACH__)) \ + || defined(__DragonFly__) || defined(__FreeBSD__) \ + || defined(__NetBSD__) || defined(__OpenBSD__) +# include +# include +# include +# include +# include +# define USE_SYSCTL +#else +# include +# include +# include +# include +#endif +// Number of elements of a table +#define numberof(x) (sizeof(x)/sizeof(x[0])) + +/* Get the current CPU time. */ +#if defined(_WIN32) +/* WINDOWS variant */ static inline unsigned long long cputime (void) { - LARGE_INTEGER freq, val; - QueryPerformanceFrequency(&freq); - QueryPerformanceCounter(&val); - return (unsigned long long) (1000000. * (double) val.QuadPart / (double) freq.QuadPart); + LARGE_INTEGER freq, val; + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&val); + return (unsigned long long) (1000000. * (double) val.QuadPart / (double) freq.QuadPart); } - #else /* UNIX variant */ -#include -#include -#include - static inline unsigned long long cputime (void) { #if defined(MULTI_THREAD_MEASURE) - // Multi thread + // Multi thread: Uses real time struct timeval tv; gettimeofday (&tv, NULL); return tv.tv_sec * 1000000ULL + tv.tv_usec; #else - // Single thread + // Single thread: Uses process usage time struct rusage rus; getrusage (0, &rus); return rus.ru_utime.tv_sec * 1000000ULL + rus.ru_utime.tv_usec; @@ -65,46 +86,64 @@ cputime (void) #endif -static unsigned long g_result; +// The result of the bench +#ifdef __cplusplus +static +#endif +unsigned long g_result; + +// The rand value static #if defined(MULTI_THREAD_MEASURE) M_THREAD_ATTR #endif unsigned int randValue = 0; +// Pseudo rand value generator. +// Not very random but sufficient and fast enough for the bench static inline void rand_init(void) { randValue = 0; } - static inline unsigned int rand_get(void) { randValue = randValue * 31421U + 6927U; return randValue; } -static inline void test_function(const char str[], size_t n, void (*func)(size_t)) +// The function that performs the bench +static inline double +test_function(const char *str, size_t n, void (*func)(size_t)) { + double result; unsigned long long start, end; rand_init(); start = cputime(); (*func)(n); end = cputime(); + result = (double)(end-start) / 1000.0; end = (end - start) / 1000U; - printf ("%s %lu ms for n = %lu [r=%lu]\n", str, (unsigned long) end, (unsigned long) n, g_result); + if (str != NULL) { + printf ("%20.20s time %lu ms for n = %lu [r=%lu]\n", str, (unsigned long) end, (unsigned long) n, g_result); + } + return result; } -#if defined(_WIN32) -# include -#elif (defined(__APPLE__) && defined(__MACH__)) \ - || defined(__DragonFly__) || defined(__FreeBSD__) \ - || defined(__NetBSD__) || defined(__OpenBSD__) -# include -# include -# define USE_SYSCTL -#else -# include +// Configuration table +typedef struct { + int num; + const char *funcname; + size_t default_n; + void (*init)(size_t); + void (*func)(size_t); + void (*clear)(void); +} config_func_t; + +// Perform a parsing of the given arguments and do the bench according to the table +#ifdef __cplusplus +extern "C" #endif +void test(size_t n, const config_func_t functions[], int argc, const char *argv[]); /* Return the number of CPU of the system */ static inline int get_cpu_count(void)