From 35a1d0d051546f0bbaae9338aa3fed4d04a9a92e Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 23 Oct 2009 18:14:55 +0000 Subject: New sandglass_bench_* macros, remove SANDGLASS_REALTICKS. sandglass_bench_fine() replaces SANDGLASS_REALTICKS; use SANDGLASS_CPUTIME instead. Also, sandglass_bench_noprecache() for when the expression to be timed has side-effects and should be executed only once. --- src/sandglass.c | 20 +---------------- src/sandglass.h | 68 +++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 57 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/sandglass.c b/src/sandglass.c index 6db28a3..f97b9c1 100644 --- a/src/sandglass.c +++ b/src/sandglass.c @@ -104,19 +104,10 @@ sandglass_real_create(sandglass_t *sandglass, switch (attr->incrementation) { case SANDGLASS_MONOTONIC: switch (attr->resolution) { - case SANDGLASS_REALTICKS: -#ifdef SANDGLASS_TSC - sandglass->resolution = sandglass_tsc_resolution(); - sandglass->loops = sandglass_tsc_loops(); - break; -#else - return -1; -#endif - case SANDGLASS_CPUTIME: #ifdef SANDGLASS_TSC sandglass->resolution = sandglass_tsc_resolution(); - sandglass->loops = 1; + sandglass->loops = sandglass_tsc_loops(); break; #else return -1; @@ -134,10 +125,6 @@ sandglass_real_create(sandglass_t *sandglass, case SANDGLASS_INTROSPECTIVE: switch (attr->resolution) { - case SANDGLASS_REALTICKS: - /* No such thing as an introspective raw TSC */ - return -1; - case SANDGLASS_CPUTIME: if (sysconf(_SC_THREAD_CPUTIME) > 0 || sysconf(_SC_CPUTIME) > 0) { sandglass->resolution = 1e9; @@ -202,7 +189,6 @@ sandglass_real_gettime(sandglass_t *sandglass) switch (sandglass->attributes.incrementation) { case SANDGLASS_MONOTONIC: switch (sandglass->attributes.resolution) { - case SANDGLASS_REALTICKS: case SANDGLASS_CPUTIME: #ifdef SANDGLASS_TSC sandglass->grains = sandglass_get_tsc(); @@ -230,10 +216,6 @@ sandglass_real_gettime(sandglass_t *sandglass) case SANDGLASS_INTROSPECTIVE: switch (sandglass->attributes.resolution) { - case SANDGLASS_REALTICKS: - /* No such thing as an introspective raw TSC */ - return -1; - case SANDGLASS_CPUTIME: if (sysconf(_SC_THREAD_CPUTIME) > 0) { if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) != 0) diff --git a/src/sandglass.h b/src/sandglass.h index 0d5e5e5..34461ba 100644 --- a/src/sandglass.h +++ b/src/sandglass.h @@ -26,6 +26,8 @@ #ifndef SANDGLASS_H_INCLUDED #define SANDGLASS_H_INCLUDED +#include + #ifdef __cplusplus /* We've been included from a C++ file; mark everything here as extern "C" */ extern "C" { @@ -65,14 +67,7 @@ enum sandglass_resolution_t * portable. Uses the CLOCK_THREAD_CPUTIME_ID clock for * SANDGLASS_INTROSPECTIVE mode, and the raw TSC for SANDGLASS_MONOTONIC. */ - SANDGLASS_CPUTIME, - - /* - * Get timing information accurate to within one CPU clock cycle - requires - * some looping and other trickery to account for TSCs which are not accurate - * to within one clock cycle. Not valid with SANDGLASS_INTROSPECTIVE. - */ - SANDGLASS_REALTICKS + SANDGLASS_CPUTIME }; typedef enum sandglass_resolution_t sandglass_resolution_t; @@ -134,16 +129,18 @@ int sandglass_elapse(sandglass_t *sandglass); #define SANDGLASS_NO_UNROLL() __asm__ __volatile__ ("") /* - * Macro to facilitate correct benchmarking of blocks of code. May be called + * Macros to facilitate correct benchmarking of blocks of code. May be called * like so: - * sandglass_bench(&sandglass, f(x)) + * sandglass_bench*(&sandglass, f(x)) * or like so: - * sandglass_bench(&sandglass, { + * sandglass_bench*(&sandglass, { * f(x); * g(x); * }); */ -#define sandglass_bench(sandglass, routine) \ + +/* Provides single clock cycle resolution in some cases */ +#define sandglass_bench_fine(sandglass, routine) \ do { \ /* Warm up the cache for these functions */ \ sandglass_begin(sandglass); \ @@ -161,6 +158,7 @@ int sandglass_elapse(sandglass_t *sandglass); \ /* Warm up the cache for our routine */ \ routine; \ + \ /* Time our routine in a loop */ \ sandglass_begin(sandglass); \ for ((sandglass)->i = 0; \ @@ -168,6 +166,7 @@ int sandglass_elapse(sandglass_t *sandglass); ++(sandglass)->i) { \ SANDGLASS_NO_UNROLL(); \ routine; \ + SANDGLASS_NO_UNROLL(); \ } \ sandglass_elapse(sandglass); \ \ @@ -176,6 +175,51 @@ int sandglass_elapse(sandglass_t *sandglass); (sandglass)->grains /= (sandglass)->loops; \ } while (0) +/* General high resolution timer */ +#define sandglass_bench(sandglass, routine) \ + do { \ + /* Warm up the cache for these functions */ \ + sandglass_begin(sandglass); \ + sandglass_elapse(sandglass); \ + \ + /* Time an empty routine for our baseline */ \ + sandglass_begin(sandglass); \ + sandglass_elapse(sandglass); \ + (sandglass)->baseline = (sandglass)->grains; \ + \ + /* Warm up the cache for our routine */ \ + routine; \ + \ + /* Time the routine */ \ + sandglass_begin(sandglass); \ + routine; \ + sandglass_elapse(sandglass); \ + \ + /* Subtract the baseline */ \ + (sandglass)->grains -= (sandglass)->baseline; \ + } while (0) + +/* Only executes routine once - useful if routine has side-effects */ +#define sandglass_bench_noprecache(sandglass, routine) \ + do { \ + /* Warm up the cache for these functions */ \ + sandglass_begin(sandglass); \ + sandglass_elapse(sandglass); \ + \ + /* Time an empty loop for our baseline */ \ + sandglass_begin(sandglass); \ + sandglass_elapse(sandglass); \ + (sandglass)->baseline = (sandglass)->grains; \ + \ + /* Time the routine */ \ + sandglass_begin(sandglass); \ + routine; \ + sandglass_elapse(sandglass); \ + \ + /* Subtract the baseline */ \ + (sandglass)->grains -= (sandglass)->baseline; \ + } while (0) + #ifdef __cplusplus } #endif -- cgit v1.2.3