From ac2c7ddf72d27de5b20adf5085fce58dea109829 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 9 Oct 2015 22:17:57 +0200 Subject: [PATCH] add hourglass benchmark - see http://static.usenix.org/publications/library/proceedings/usenix02/tech/freenix/regehr.html --- hermit/.gitignore | 1 + hermit/usr/benchmarks/Makefile | 13 +- hermit/usr/benchmarks/hg.c | 51 ++++++ hermit/usr/benchmarks/hist.c | 78 ++++++++ hermit/usr/benchmarks/hist.h | 31 ++++ hermit/usr/benchmarks/init.c | 47 +++++ hermit/usr/benchmarks/init.h | 27 +++ hermit/usr/benchmarks/opt.c | 124 +++++++++++++ hermit/usr/benchmarks/opt.h | 38 ++++ hermit/usr/benchmarks/rdtsc.c | 314 +++++++++++++++++++++++++++++++++ hermit/usr/benchmarks/rdtsc.h | 73 ++++++++ hermit/usr/benchmarks/report.c | 79 +++++++++ hermit/usr/benchmarks/report.h | 28 +++ hermit/usr/benchmarks/run.c | 161 +++++++++++++++++ hermit/usr/benchmarks/run.h | 50 ++++++ hermit/usr/benchmarks/setup.c | 40 +++++ hermit/usr/benchmarks/setup.h | 27 +++ 17 files changed, 1179 insertions(+), 3 deletions(-) create mode 100644 hermit/usr/benchmarks/hg.c create mode 100644 hermit/usr/benchmarks/hist.c create mode 100644 hermit/usr/benchmarks/hist.h create mode 100644 hermit/usr/benchmarks/init.c create mode 100644 hermit/usr/benchmarks/init.h create mode 100644 hermit/usr/benchmarks/opt.c create mode 100644 hermit/usr/benchmarks/opt.h create mode 100644 hermit/usr/benchmarks/rdtsc.c create mode 100644 hermit/usr/benchmarks/rdtsc.h create mode 100644 hermit/usr/benchmarks/report.c create mode 100644 hermit/usr/benchmarks/report.h create mode 100644 hermit/usr/benchmarks/run.c create mode 100644 hermit/usr/benchmarks/run.h create mode 100644 hermit/usr/benchmarks/setup.c create mode 100644 hermit/usr/benchmarks/setup.h diff --git a/hermit/.gitignore b/hermit/.gitignore index 6e2b38d36..e315b12b9 100644 --- a/hermit/.gitignore +++ b/hermit/.gitignore @@ -20,5 +20,6 @@ usr/tests/hellof usr/tests/jacobi usr/tests/thr_hello usr/benchmarks/stream +usr/benchmarks/hg usr/x86/ usr/tmp/ diff --git a/hermit/usr/benchmarks/Makefile b/hermit/usr/benchmarks/Makefile index f1df1a615..b48d0dac4 100644 --- a/hermit/usr/benchmarks/Makefile +++ b/hermit/usr/benchmarks/Makefile @@ -43,7 +43,7 @@ endif default: all -all: stream +all: stream hg stream.o: stream.c @echo [CC] $@ @@ -56,13 +56,20 @@ stream: stream.o $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ $Qchmod a-x $@.sym +hg: hg.o hist.o rdtsc.o run.o init.o opt.o report.o setup.o + @echo [LD] $@ + $Q$(CC_FOR_TARGET) $(LDFLAGS_FOR_TARGET) $(CFLAGS_FOR_TARGET) -o $@ $< hist.o rdtsc.o run.o init.o opt.o report.o setup.o + $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym + $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@ + $Qchmod a-x $@.sym + clean: @echo Cleaning benchmarks - $Q$(RM) stream *.sym *.o *~ + $Q$(RM) stream hg *.sym *.o *~ veryclean: @echo Propper cleaning benchmarks - $Q$(RM) stream *.sym *.o *~ + $Q$(RM) stream hg *.sym *.o *~ depend: $Q$(CC_FOR_TARGET) -MM $(CFLAGS_FOR_TARGET) *.c > Makefile.dep diff --git a/hermit/usr/benchmarks/hg.c b/hermit/usr/benchmarks/hg.c new file mode 100644 index 000000000..52d2108c4 --- /dev/null +++ b/hermit/usr/benchmarks/hg.c @@ -0,0 +1,51 @@ +/* + * ===================================================================================== + * + * Filename: main.c + * + * Description: + * + * Version: 1.0 + * Created: 25.07.2014 14:59:20 + * Revision: none + * Compiler: gcc + * + * Author: Georg Wassen (gw) (), + * Company: + * + * ===================================================================================== + */ + +#include "opt.h" +#include "init.h" +#include "setup.h" +#include "run.h" +#include "report.h" + +#include +#include + +struct opt opts = {0}; +struct result results = {0}; + +int main(int argc, char *argv[]) +{ + printf("hourglass\n"); + + opt(argc, argv, &opts); + init(&opts); + + report_params(&opts); + + setup(&opts); + run(&opts, &results); + setdown(&opts); + + report(&opts, &results); + + run_free(&opts, &results); + + deinit(&opts); + + return EXIT_SUCCESS; +} diff --git a/hermit/usr/benchmarks/hist.c b/hermit/usr/benchmarks/hist.c new file mode 100644 index 000000000..3d0c948ec --- /dev/null +++ b/hermit/usr/benchmarks/hist.c @@ -0,0 +1,78 @@ +/* + * ===================================================================================== + * + * Filename: hist.c + * + * Description: + * + * Version: 1.0 + * Created: 26.07.2014 20:02:34 + * Revision: none + * Compiler: gcc + * + * Author: Georg Wassen (gw) (), + * Company: + * + * ===================================================================================== + */ + +#include "hist.h" + +#include +#include +#include +#include + +static const struct opt *opts; +static uint32_t *hists; + +uint32_t *hist_alloc(const struct opt *opt) +{ + opts = opt; + hists = calloc(opt->hist_cnt, sizeof(uint32_t)); + hist_reset(); + return hists; +} + +int hist_reset(void) +{ + unsigned i; + for (i=0; ihist_cnt; i++) { + hists[i] = 0; + } + return 0; +} + +void hist_add(uint64_t t) +{ + t /= opts->hist_width; + if (t > opts->hist_cnt-1) t = opts->hist_cnt-1; + hists[t]++; +} + +int hist_print(void) +{ + unsigned i; + unsigned max=0; + const size_t bar_width = 30; + char bar[bar_width+1]; + + for (i=0; ihist_cnt; i++) { + if (hists[i] > max) max = hists[i]; + } + max = (unsigned)ceil(log10((double)max)); + if (max == 0) max = 1; + memset(bar, '*', bar_width); + bar[bar_width] = 0; + + printf("Histogram (%u bins with %u ticks each)\n", opts->hist_cnt, opts->hist_width); + for (i=0; ihist_cnt; i++) { + printf(" %5u : %5u..%5u : %-10u %s\n", i, + (unsigned)(i*opts->hist_width), + (unsigned)((i+1)*opts->hist_width-1), + (unsigned)(hists[i]), + (char*)bar+(unsigned)(bar_width-((log10(hists[i]+1.)*bar_width)/max))); + } + return 0; +} + diff --git a/hermit/usr/benchmarks/hist.h b/hermit/usr/benchmarks/hist.h new file mode 100644 index 000000000..249f80ddb --- /dev/null +++ b/hermit/usr/benchmarks/hist.h @@ -0,0 +1,31 @@ +/* + * ===================================================================================== + * + * Filename: hist.h + * + * Description: + * + * Version: 1.0 + * Created: 26.07.2014 20:02:48 + * Revision: none + * Compiler: gcc + * + * Author: Georg Wassen (gw) (), + * Company: + * + * ===================================================================================== + */ + +#ifndef __HIST_H__ +#define __HIST_H__ + +#include "opt.h" + +#include + +uint32_t *hist_alloc(const struct opt *opt); +int hist_reset(void); +void hist_add(uint64_t t); +int hist_print(void); + +#endif // __HIST_H__ diff --git a/hermit/usr/benchmarks/init.c b/hermit/usr/benchmarks/init.c new file mode 100644 index 000000000..dbf917688 --- /dev/null +++ b/hermit/usr/benchmarks/init.c @@ -0,0 +1,47 @@ +/* + * ===================================================================================== + * + * Filename: init.c + * + * Description: + * + * Version: 1.0 + * Created: 25.07.2014 15:06:05 + * Revision: none + * Compiler: gcc + * + * Author: Georg Wassen (gw) (), + * Company: + * + * ===================================================================================== + */ + +#include "init.h" +#include "rdtsc.h" + + +int init(struct opt *opt) +{ + /* + * initialize (if required) + * e.g. read number of processors available or cache parameters + */ + + opt->tps = rdtsc_ticks_per_sec(); // does not work reliably... + //opt->tps = 2530000000; + + + return 0; +} + + + +int deinit(struct opt *opt) +{ + /* + * de-initialize (if required) + * e.g. free allocated resources + */ + + return 0; +} diff --git a/hermit/usr/benchmarks/init.h b/hermit/usr/benchmarks/init.h new file mode 100644 index 000000000..81c8e7e95 --- /dev/null +++ b/hermit/usr/benchmarks/init.h @@ -0,0 +1,27 @@ +/* + * ===================================================================================== + * + * Filename: init.h + * + * Description: + * + * Version: 1.0 + * Created: 25.07.2014 15:05:13 + * Revision: none + * Compiler: gcc + * + * Author: Georg Wassen (gw) (), + * Company: + * + * ===================================================================================== + */ + +#ifndef __INIT_H__ +#define __INIT_H__ + +#include "opt.h" + +int init(struct opt *opt); +int deinit(struct opt *opt); + +#endif // __INIT_H__ diff --git a/hermit/usr/benchmarks/opt.c b/hermit/usr/benchmarks/opt.c new file mode 100644 index 000000000..26cd9c95e --- /dev/null +++ b/hermit/usr/benchmarks/opt.c @@ -0,0 +1,124 @@ +/* + * ===================================================================================== + * + * Filename: opt.c + * + * Description: + * + * Version: 1.0 + * Created: 25.07.2014 15:01:32 + * Revision: none + * Compiler: gcc + * + * Author: Georg Wassen (gw) (), + * Company: + * + * ===================================================================================== + */ + +#define _GNU_SOURCE +#include "opt.h" + +#include +#include +#include +#include +#include + +#ifdef __hermit__ +char *basename(char *path) +{ + char *p; + if( path == NULL || *path == '\0' ) + return "."; + p = path + strlen(path) - 1; + while( *p == '/' ) { + if( p == path ) + return path; + *p-- = '\0'; + } + while( p >= path && *p != '/' ) + p--; + return p + 1; +} +#endif + +int opt(int argc, char *argv[], struct opt *opt) +{ + char c; + char *p; + + opt->secs = 4; + opt->mode = stat; + opt->threshold = 0; + + opt->hist_cnt = 100; + opt->hist_width = 50; + + opt->list_cnt = 1000; + + + /* + * read command line arguments and store them in opt + */ + + while ((c = getopt(argc, argv, "b:c:d:hr:t:")) != -1) { + switch (c) { + case 'h' : + printf("usage: %s \n", basename(argv[0])); + printf(" -h help \n"); + printf(" -d N duration (in sec or 1m, 1h) \n"); + printf(" -r R report: hist, list\n"); + printf(" -c N count (hist or list)\n"); + printf(" -b N hist bin width (in ticks)\n"); + printf(" -t N threshold (in ticks)\n"); + exit(1); + break; + case 'd' : + opt->secs = (unsigned)strtoul(optarg, &p, 0); + if (p[0] == 'm' || p[0] == 'M') opt->secs *= 60u; + else if (p[0] == 'h' || p[0] == 'H') opt->secs *= (60u*60u); + else if (strlen(p) > 0) { + printf("ERROR: Parameter: unrecognized characters in time: '%s'\n", p); + return 2; + } + break; + case 'r' : + if (strncmp(optarg, "hist", 4) == 0) { + opt->mode = hist; + } else if (strncmp(optarg, "list", 4) == 0) { + opt->mode = list; + } + break; + case 'c' : + if (opt->mode == hist) { + opt->hist_cnt = (unsigned)strtoul(optarg, &p, 0); + } else if (opt->mode == list) { + opt->list_cnt = (unsigned)strtoul(optarg, &p, 0); + } + break; + case 'b' : + opt->hist_width = (unsigned)strtoul(optarg, &p, 0); + break; + case 't' : + opt->threshold = (unsigned)strtoul(optarg, &p, 0); + break; + } + } + + if (opt->mode == hist) { + if (opt->hist_cnt == 0) { + opt->hist_cnt = 1; + } + if (opt->hist_width == 0) { + opt->hist_width = 1; + } + } else if (opt->mode == list) { + if (opt->list_cnt == 0) { + opt->list_cnt = 1; + } + } + + return 0; +} + diff --git a/hermit/usr/benchmarks/opt.h b/hermit/usr/benchmarks/opt.h new file mode 100644 index 000000000..229485f33 --- /dev/null +++ b/hermit/usr/benchmarks/opt.h @@ -0,0 +1,38 @@ +/* + * ===================================================================================== + * + * Filename: opt.h + * + * Description: + * + * Version: 1.0 + * Created: 25.07.2014 15:02:15 + * Revision: none + * Compiler: gcc + * + * Author: Georg Wassen (gw) (), + * Company: + * + * ===================================================================================== + */ + +#ifndef __OPT_H__ +#define __OPT_H__ + +#include + +struct opt { + unsigned secs; + enum {stat, hist, list} mode; + uint64_t tps; + uint64_t threshold; + + unsigned hist_cnt; + unsigned hist_width; + + unsigned list_cnt; +}; + +int opt(int argc, char *argv[], struct opt *opt); + +#endif // __OPT_H__ diff --git a/hermit/usr/benchmarks/rdtsc.c b/hermit/usr/benchmarks/rdtsc.c new file mode 100644 index 000000000..31c47afe4 --- /dev/null +++ b/hermit/usr/benchmarks/rdtsc.c @@ -0,0 +1,314 @@ +/* + * ===================================================================================== + * + * Filename: rdtsc.c + * + * Description: + * + * Version: 1.0 + * Created: 31.01.2011 10:56:58 + * Revision: none + * Compiler: gcc + * + * Author: Georg Wassen (gw) (), + * Company: + * + * ===================================================================================== + */ + +#define _SVID_SOURCE +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include +#include "rdtsc.h" + +static inline void cpuid(unsigned func, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx) { + __asm__ volatile ("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(func)); +} + +static inline uint32_t cpuid_edx(uint32_t code) { + uint32_t eax, ebx, ecx, edx; + + cpuid(code, &eax, &ebx, &ecx, &edx); + + return edx; +} + +static uint64_t tps = 0; + +#if 0 +/* + * === FUNCTION ====================================================================== + * Name: second() + * Description: returns a double representation of gettimeofday (seconds.microseconds) + * ===================================================================================== + */ +static inline double second() +{ + struct timeval tv; + gettimeofday(&tv, 0); + return tv.tv_sec + 1e-6*tv.tv_usec; +} + +/* + * === FUNCTION ====================================================================== + * Name: selectsleep(us) + * Description: calls select() to sleep (wait) the given microseconds + * ===================================================================================== + */ +static inline void selectsleep(unsigned us) +{ + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = us; + select(0,0,0,0,&tv); // portable way to sleep with subsecond precision +} + +/* + * === FUNCTION ====================================================================== + * Name: rdtsc_ticks_per_sec() + * Description: uses least squares regressen to measure the frequency of the TSC + * ===================================================================================== + */ +uint64_t rdtsc_ticks_per_sec(void) +{ + double sumx = 0, sumy = 0; + double sumxx = 0, sumxy = 0; + double slope; + // least squared linear regression taken from mcert/misc/realfeed/realfeel.c + + const unsigned n = 30; + unsigned i; + + for (i=0; i tv1.tv_usec) + diff_usec += tv2.tv_usec - tv1.tv_usec; + else + diff_usec += tv1.tv_usec - tv2.tv_usec; + + //printf("diff usec: %llu\n", + // (unsigned long long)diff_usec); + + return (diff_tsc*1000000) / diff_usec; +#endif +} + +/* + * === FUNCTION ====================================================================== + * Name: rdtsc_max_freq(id) + * Description: reads the maximum frequency of given CPU-ID from /sys/.../cpuN/cpufreq + * Changes: WASSEN, 24.5.2011: taken from hourglass via irqlab + * ===================================================================================== + */ +uint64_t rdtsc_max_freq(int id) +{ + uint64_t mhz = -1; + char fname[BUFSIZ]; + char processor[BUFSIZ]; + char *buffer, *loc; + FILE *fp; + double tmhz; + int ret; + + sprintf(fname, "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", id); + + if (NULL == (fp = fopen(fname, "r"))) { + fprintf(stderr, "Can't open <%s>.\n", fname); + fprintf(stderr, "Trying (not as accurate)\n"); + + if(NULL == (fp = fopen("/proc/cpuinfo","r"))) { + fprintf(stderr, "Can't open .\n"); + return -1; + } + + + buffer = (void *) malloc(sizeof(char) * 1024 * 512); + ret = fread(buffer, sizeof(char), 1024 * 512, fp); + if (ret == 0) { + fprintf(stderr, "fread() returned 0: %s\n", strerror(errno)); + return -1; + } + + sprintf(processor, "processor\t: %d", id); + if(NULL == (loc = strstr(buffer, processor))) { + fprintf(stderr, "Unable to parse /proc/cpuinfo\n"); + return -1; + } + if(NULL == (loc = strstr(loc, "cpu MHz"))) { + fprintf(stderr, "Unable to parse /proc/cpuinfo\n"); + return -1; + } + loc += strlen("cpu MHz"); + while(!isdigit(*loc)) + loc++; + loc--; + sscanf(loc, "%lf", &tmhz); + mhz = (uint64_t)(tmhz); + mhz*=1000; + free(buffer); + } else { + ret = fscanf(fp, "%lld", (unsigned long long*)&mhz); + if (ret == 0) { + fprintf(stderr, "fscanf() returned 0: %s\n", strerror(errno)); + return -1; + } + fclose(fp); + } + + return mhz*1000; +} + +/* + * === FUNCTION ====================================================================== + * Name: rdtsc_loop(ticks) + * Description: waits actively for given TSC ticks + * ===================================================================================== + */ +void rdtsc_loop(uint64_t ticks) +{ + uint64_t t_now = 0, t_end; + rdtsc(&t_now); + t_end = t_now + ticks; + while (t_now < t_end) { + rdtsc(&t_now); + } +} + +/* + * === FUNCTION ====================================================================== + * Name: rdtsc_loop_sec(ticks) + * Description: waits actively for given seconds + * ATTN: needs rdtsc_ticks_per_sec() unless that function was previously + * called (this function MIGHT use syscalls!) + * ===================================================================================== + */ +void rdtsc_loop_sec(unsigned seconds) +{ + uint64_t t_now = 0, t_end; + rdtsc(&t_now); + if (tps == 0) rdtsc_ticks_per_sec(); + t_end = t_now + (uint64_t)seconds * tps; + while (t_now < t_end) { + rdtsc(&t_now); + } +} + +/* + * test if TSC is invariant (return value 1) + */ +int rdtsc_is_invariant(void) { + if (cpuid_edx(0x80000007) & (1 << 8)) { // TSC is invariant + return 1; + } + + return 0; +} + +/* + * measure overhead of *not* serialized rdtsc() (SHL, MOV, OR) + */ +uint64_t rdtsc_get_overhead(const uint64_t iterations) { + uint64_t c; + uint64_t tsc_overhead_notserial = 0; + uint64_t tsc_start; + uint64_t tsc_end; + + if (iterations == 0) { + return 0; + } + + for (c = 0; c < iterations; c++) { +#if ! __MIC__ + __asm__ volatile("lfence"); +#else + __asm__ volatile("lock; add $0, 0(%%rsp)" ::: "memory"); +#endif + rdtsc(&tsc_start); + rdtsc(&tsc_end); + tsc_overhead_notserial += tsc_end - tsc_start; + } + + return tsc_overhead_notserial / iterations; +} + +/* + * measure overhead of serialized rdtsc_serialized() (LFENCE, SHL, MOV, OR, LFENCE) + */ +uint64_t rdtsc_get_overhead_serialized(const uint64_t iterations) { + uint64_t c; + uint64_t tsc_overhead_serial = 0; + uint64_t tsc_start; + uint64_t tsc_end; + + if (iterations == 0) { + return 0; + } + + for (c = 0; c < iterations; c++) { + rdtsc_serialized(&tsc_start); + rdtsc_serialized(&tsc_end); + tsc_overhead_serial += tsc_end - tsc_start; + } + + return tsc_overhead_serial / iterations; +} diff --git a/hermit/usr/benchmarks/rdtsc.h b/hermit/usr/benchmarks/rdtsc.h new file mode 100644 index 000000000..0b7449ddb --- /dev/null +++ b/hermit/usr/benchmarks/rdtsc.h @@ -0,0 +1,73 @@ +/* + * ===================================================================================== + * + * Filename: rdtsc.c + * + * Description: + * + * Version: 1.0 + * Created: 24.01.2011 13:41:30 + * Revision: none + * Compiler: gcc + * + * Author: Georg Wassen (gw) (), + * Company: + * + * ===================================================================================== + */ + +#ifndef RDTSC_H +#define RDTSC_H + +#include + +/* + * rdtsc_ticks_per_sec(): measure frequency. Takes below a second. + */ +uint64_t rdtsc_ticks_per_sec(void) __attribute__((optimize(3))); + + +typedef union __attribute__((__transparent_union__)) +{ + uint64_t *__u64; + struct {uint32_t __low; uint32_t __high;} *__u32; +} tsc_t; + +/* + * rdtsc(): Register-save version (compiler may insert additional push/pop) + * (clobbered-registers not given b/c compiler deduces from output-registers) + */ +static inline void __attribute__((__always_inline__, gnu_inline, optimize(3))) rdtsc(tsc_t tsc) +{ + __asm__ volatile ("rdtsc" : "=a"(tsc.__u32->__low), "=d"(tsc.__u32->__high) ); +} + +/* + * rdtsc_serial(): get RDTSC with leading and rear serializing LFENCE instruction + */ +static inline void __attribute__((__always_inline__, gnu_inline, optimize(3))) rdtsc_serialized(tsc_t tsc) +{ +#if ! __MIC__ + __asm__ volatile ( + "lfence\n\t" // serialize (needs SSE2, available since AMD Athlon64, Intel Core) + "rdtsc\n\t" + "lfence\n\t" + : "=a"(tsc.__u32->__low), "=d"(tsc.__u32->__high) ); +#else + __asm__ volatile ( + "lock; add $0, 0(%%rsp)\n\t" // serialize + "rdtsc\n\t" + "lock; add $0, 0(%%rsp)\n\t" // serialize + : "=a"(tsc.__u32->__low), "=d"(tsc.__u32->__high) :: "memory" ); +#endif +} + +void rdtsc_loop(uint64_t ticks); +void rdtsc_loop_sec(unsigned seconds); +uint64_t rdtsc_max_freq(int id); + +int rdtsc_is_invariant(void); +uint64_t rdtsc_get_overhead(uint64_t iterations); +uint64_t rdtsc_get_overhead_serialized(uint64_t iterations); + +#endif diff --git a/hermit/usr/benchmarks/report.c b/hermit/usr/benchmarks/report.c new file mode 100644 index 000000000..2fca1cade --- /dev/null +++ b/hermit/usr/benchmarks/report.c @@ -0,0 +1,79 @@ +/* + * ===================================================================================== + * + * Filename: report.c + * + * Description: + * + * Version: 1.0 + * Created: 25.07.2014 15:11:54 + * Revision: none + * Compiler: gcc + * + * Author: Georg Wassen (gw) (), + * Company: + * + * ===================================================================================== + */ + +#include "report.h" +#include "hist.h" + +#include + + +int report_params(const struct opt *opt) +{ + printf("init: tps = %llu\n", (unsigned long long)opt->tps); + printf("secs : %u\n", opt->secs); + printf("threshold : %llu\n", (unsigned long long)opt->threshold); + if (opt->mode == hist) { + printf("mode : histogram (cnt: %u, width: %u)\n", opt->hist_cnt, opt->hist_width); + } else if (opt->mode == list) { + printf("mode : list (cnt: %u)\n", opt->list_cnt); + } + return 0; +} + +static int report_stat(const struct result *result) +{ + printf(" # loops : %15llu\n", + (unsigned long long)result->cnt); + printf(" Min. : %15llu (@loop #%llu)\n", + (unsigned long long)result->min, + (unsigned long long)result->t_min); + printf(" Avg. : %18.2lf\n", + (double)result->sum/(double)result->cnt); + printf(" Max. : %15llu (@loop #%llu)\n", + (unsigned long long)result->max, + (unsigned long long)result->t_max); + return 0; +} + +int report(const struct opt *opt, const struct result *result) +{ + /* + * write results to stdout (or file) + * depending on opt + */ + + printf("Dummy result: %llu \n", (unsigned long long)result->dummy); + + report_stat(result); + + if (opt->mode == hist) { + hist_print(); + } else if (opt->mode == list) { + unsigned i; + for (i=0; ilist_cnt; i++) { + if (result->list[i].time > 0) { + printf(" %15llu : %10llu\n", + (unsigned long long)result->list[i].time, + (unsigned long long)result->list[i].gap); + } else break; + } + + } + + return 0; +} diff --git a/hermit/usr/benchmarks/report.h b/hermit/usr/benchmarks/report.h new file mode 100644 index 000000000..477e34848 --- /dev/null +++ b/hermit/usr/benchmarks/report.h @@ -0,0 +1,28 @@ +/* + * ===================================================================================== + * + * Filename: report.h + * + * Description: + * + * Version: 1.0 + * Created: 25.07.2014 15:11:07 + * Revision: none + * Compiler: gcc + * + * Author: Georg Wassen (gw) (), + * Company: + * + * ===================================================================================== + */ + +#ifndef __REPORT_H__ +#define __REPORT_H__ + +#include "run.h" +#include "opt.h" + +int report_params(const struct opt *opt); +int report(const struct opt *opt, const struct result *result); + +#endif // __REPORT_H__ diff --git a/hermit/usr/benchmarks/run.c b/hermit/usr/benchmarks/run.c new file mode 100644 index 000000000..e15555085 --- /dev/null +++ b/hermit/usr/benchmarks/run.c @@ -0,0 +1,161 @@ +/* + * ===================================================================================== + * + * Filename: run.c + * + * Description: + * + * Version: 1.0 + * Created: 25.07.2014 15:10:30 + * Revision: none + * Compiler: gcc + * + * Author: Georg Wassen (gw) (), + * Company: + * + * ===================================================================================== + */ + +#include "run.h" +#include "rdtsc.h" +#include "hist.h" + +#include +#include + +static struct result *results; +static const struct opt *opts; + + +static void store_results_stat(uint64_t gap, uint64_t offset) +{ + + if (gap < results->min) { + results->min = gap; + results->t_min = results->cnt; + } + if (gap > results->max) { + results->max = gap; + results->t_max = results->cnt; + } + results->sum += gap; + results->cnt++; /* avg = sum/cnt */ +} + +static void store_results_hist(uint64_t gap, uint64_t offset) +{ + /* + * create histogram + */ + store_results_stat(gap, offset); + hist_add(gap); +} + +static unsigned list_cnt; +static unsigned list_idx = 0; +static void store_results_list(uint64_t gap, uint64_t offset) +{ + /* + * store all timestamps + */ + if (list_idx >= list_cnt) return; + store_results_stat(gap, offset); + results->list[list_idx].time = offset; + results->list[list_idx].gap = gap; + list_idx++; +} + +static void (*store_results)(uint64_t gap, uint64_t offset); + + +static int reset_results(void) +{ + results->min=UINT64_MAX; + results->max=0; + results->sum=0; + results->cnt=0; + results->t_min = 0; + results->t_max = 0; + if (opts->mode == hist) { + hist_reset(); + } else if (opts->mode == list) { + unsigned i; + for (i=0; ilist_cnt; i++) { + results->list[i].time=0; + results->list[i].gap=0; + } + list_idx = 0; + } + return 0; +} + +static int hourglass(uint64_t duration, uint64_t threshold) +{ + uint64_t t1, t2, t_end, diff; /* timestamps */ + + reset_results(); + + rdtsc(&t1); /* start-time */ + t_end = t1 + duration; /* calculate end-time */ + + while (t1 < t_end) { /* loop until end-time */ + t2 = t1; + rdtsc(&t1); + diff = t1 - t2; + if (diff > threshold) { + store_results(diff, t2); + } + /* Note: additional workload may be added here */ + } + return 0; +} + +int run(const struct opt *opt, struct result *result) +{ + unsigned i; + results = result; + opts = opt; + + results->hist = NULL; + + switch (opt->mode) { + case stat : + store_results = store_results_stat; + break; + case hist : + store_results = store_results_hist; + results->hist = hist_alloc(opt); + hist_reset(); + break; + case list : + store_results = store_results_list; + list_cnt = opt->list_cnt; + results->list = calloc(opt->list_cnt, sizeof(struct res_list)); + for (i=0; ilist_cnt; i++) { + results->list[i].time=0; + results->list[i].gap=0; + } + break; + } + + /* + * execute hourglass routine + */ + hourglass(1 * opt->tps, opt->threshold); // 1 sec warmup + + hourglass(opt->secs * opt->tps, opt->threshold); + return 0; +} + +int run_free(const struct opt *opt, struct result *result) +{ + if (results->hist != NULL) { + free(results->hist); + results->hist = NULL; + } + if (results->list != NULL) { + free(results->list); + results->list = NULL; + } + return 0; +} diff --git a/hermit/usr/benchmarks/run.h b/hermit/usr/benchmarks/run.h new file mode 100644 index 000000000..f0f52fbc3 --- /dev/null +++ b/hermit/usr/benchmarks/run.h @@ -0,0 +1,50 @@ +/* + * ===================================================================================== + * + * Filename: run.h + * + * Description: + * + * Version: 1.0 + * Created: 25.07.2014 15:08:43 + * Revision: none + * Compiler: gcc + * + * Author: Georg Wassen (gw) (), + * Company: + * + * ===================================================================================== + */ + +#ifndef __RUN_H__ +#define __RUN_H__ + +#include "opt.h" + +#include +struct res_list { + uint64_t time; + uint64_t gap; +}; + +struct result { + uint64_t dummy; + + uint64_t min; + uint64_t max; + uint64_t sum; + uint64_t cnt; + uint64_t t_min; + uint64_t t_max; + + uint32_t *hist; + struct res_list *list; + +}; + +int run(const struct opt *opt, struct result *result); +int run_free(const struct opt *opt, struct result *result); + + +#endif // __RUN_H__ + diff --git a/hermit/usr/benchmarks/setup.c b/hermit/usr/benchmarks/setup.c new file mode 100644 index 000000000..435682dc8 --- /dev/null +++ b/hermit/usr/benchmarks/setup.c @@ -0,0 +1,40 @@ +/* + * ===================================================================================== + * + * Filename: setup.c + * + * Description: + * + * Version: 1.0 + * Created: 25.07.2014 15:07:43 + * Revision: none + * Compiler: gcc + * + * Author: Georg Wassen (gw) (), + * Company: + * + * ===================================================================================== + */ + +#include "setup.h" + + +int setup(struct opt *opt) +{ + /* + * set up run-time environment for benchmark + * depending on opt + * e.g. create cpu-set, move IRQs, etc. + */ + + + return 0; +} + +int setdown(struct opt *opt) +{ + /* + * undo things from setup() + */ + return 0; +} diff --git a/hermit/usr/benchmarks/setup.h b/hermit/usr/benchmarks/setup.h new file mode 100644 index 000000000..f8a889dde --- /dev/null +++ b/hermit/usr/benchmarks/setup.h @@ -0,0 +1,27 @@ +/* + * ===================================================================================== + * + * Filename: setup.h + * + * Description: + * + * Version: 1.0 + * Created: 25.07.2014 15:06:59 + * Revision: none + * Compiler: gcc + * + * Author: Georg Wassen (gw) (), + * Company: + * + * ===================================================================================== + */ + +#ifndef __SETUP_H__ +#define __SETUP_H__ + +#include "opt.h" + +int setup(struct opt *opt); +int setdown(struct opt *opt); + +#endif // __SETUP_H__