diff options
Diffstat (limited to 'benchmarks/harness.h')
| -rw-r--r-- | benchmarks/harness.h | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/benchmarks/harness.h b/benchmarks/harness.h new file mode 100644 index 0000000..72164b4 --- /dev/null +++ b/benchmarks/harness.h @@ -0,0 +1,94 @@ +#include <stdint.h> +#include <time.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static uint64_t time_get_ns (void) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + return (uint64_t)ts.tv_sec * 1000UL*1000UL*1000UL + (uint64_t)ts.tv_nsec; +} + +uint64_t read_energy_uj (void) { + FILE *f = fopen("/sys/class/powercap/intel-rapl/intel-rapl:0/energy_uj", "r"); + if (!f) { + perror("Failed to open energy counter (Are you running with sudo?)"); + return 0; + } + uint64_t energy; + if (fscanf(f, "%lu", &energy) != 1) { + energy = 0; + } + fclose(f); + return energy; +} + +#define BLACK_BOX(x) \ + __asm__ __volatile__("" : "+g"(x)) + +#define MIN(A,B) (A) < (B) ? (A) : (B) + +void bench_ ( + char const* const name, + #ifdef CONST_BUFFER + size_t(*f)(char const*, size_t), + char const* buffer, + #else + size_t(*f)(char*, size_t), + char* buffer, + #endif + size_t buffer_size, + FILE* out +) { + int64_t budget = 5UL*1000UL*1000UL*1000UL; + + uint64_t best = UINT64_MAX; + uint64_t best_energy = UINT64_MAX; + + #ifndef CONST_BUFFER + char* const tmp_buf = (char*)malloc(buffer_size); + memcpy(tmp_buf, buffer, buffer_size); + #endif + + uint64_t res = f(buffer, buffer_size); + + fprintf(out, + " <benchmark name=\"%s\">\n" + " <res>%zu</res>\n", + name, + res + ); + + while (budget > 0) { + #ifndef CONST_BUFFER + memcpy(buffer, tmp_buf, buffer_size); + #endif + uint64_t start_energy = read_energy_uj(); + uint64_t start = time_get_ns(); + res = f(buffer, buffer_size); + uint64_t elapsed = time_get_ns() - start; + best = MIN(best, elapsed); + best_energy = MIN(best_energy, read_energy_uj() - start_energy); + budget -= elapsed; + BLACK_BOX(res); + } + + fprintf(out, + " <time unit=\"ns\">%zu</time>\n" + " <throughput unit=\"MiB/s\">%f</throughput>\n", + best, + ((double)(buffer_size) / (1024.0*1024.0)) / ((double)(best) / (1000.0*1000.0*1000.0)) + ); + + if (best_energy != 0) { + fprintf(out, + " <energy-consumption unit=\"J/GiB\">%f</energy-consumption>\n", + ((double)(best_energy) / (1000.0*1000.0)) / ((double)(buffer_size) / (1024.0*1024.0*1024.0)) + ); + } + fprintf(out, " </benchmark>\n"); +} + +#define bench(FN) bench_(#FN, FN, buffer, buf_size, out) + |
