1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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)
|