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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
#if defined(__linux__)
# define _GNU_SOURCE
# include <sched.h>
#endif
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#ifdef BENCHMARK_LIB
# include BENCHMARK_LIB
#else
# include "../zahl.h"
# define BIGINT_LIBRARY "libzahl"
#endif
#ifndef LIBRARY_SUFFIX
# define LIBRARY_SUFFIX ""
#endif
#ifndef USE_CPU
# define USE_CPU 0
#endif
#ifndef CLOCK_MONOTONIC_RAW
# define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
#endif
#ifdef __x86_64__
# define RDTSC_MAYBE_SUPPORTED
#endif
#if !defined(USE_RDTSC) && !defined(USE_CLOCK) && !defined(USE_GETTIME)
# if 1 && defined(RDTSC_MAYBE_SUPPORTED) && defined(__linux__)
# define USE_RDTSC
# elif 1
# define USE_CLOCK
# else
# define USE_GETTIME
# endif
#endif
static struct timespec dur;
static char timebuf[512];
#if defined(USE_RDTSC) && defined(__x86_64__)
typedef unsigned long long int rdtsc_t;
static unsigned int start_high, start_low, end_high, end_low;
static unsigned long long int freq;
# define TIC (rdtsc(&start_low, &start_high))
# define TOC\
do {\
rdtsc_t dur_cycles;\
double dur_seconds;\
rdtsc(&end_low, &end_high);\
dur_cycles = rdtsc_join(end_low, end_high);\
dur_cycles -= rdtsc_join(start_low, start_high);\
dur_seconds = (double)dur_cycles;\
dur_seconds /= 1000 * (double)freq;\
dur_seconds -= (double)(dur.tv_sec = (int)dur_seconds);\
dur.tv_nsec = (long int)(dur_seconds * 1000000000L);\
} while (0)
static inline void
rdtsc(unsigned int *low, unsigned int *high)
{
__asm__ __volatile__ ("rdtsc" : "=a"(*low), "=d"(*high));
}
static inline rdtsc_t
rdtsc_join(unsigned int low, unsigned int high)
{
return (rdtsc_t)low | (((rdtsc_t)high) << 32);
}
#elif defined(USE_CLOCK)
static clock_t start, end;
# define TIC (start = clock())
# define TOC\
do {\
end = clock();\
dur.tv_sec = (end - start) / 1000000ULL;\
dur.tv_nsec = ((end - start) % 1000000ULL) * 1000;\
} while (0)
#elif defined(USE_GETTIME)
static struct timespec start;
# define TIC clock_gettime(CLOCK_MONOTONIC_RAW, &start)
# define TOC\
do {\
clock_gettime(CLOCK_MONOTONIC_RAW, &dur);\
dur.tv_sec -= start.tv_sec;\
dur.tv_nsec -= start.tv_nsec;\
if (dur.tv_nsec < 0) {\
dur.tv_nsec += 1000000000L;\
dur.tv_sec -= 1;\
}\
} while (0)
#endif
#define TICKS ((unsigned long long int)(dur.tv_sec) * 1000000000ULL + (unsigned long long int)(dur.tv_nsec))
#define STIME (sprintf(timebuf, "%lli.%09li", (long long)(dur.tv_sec), dur.tv_nsec), timebuf)
static void
benchmark_init(void)
{
#if defined(__linux__)
cpu_set_t cpuset;
# if defined(USE_RDTSC)
FILE *f;
char *line = 0;
size_t size = 0;
char path[PATH_MAX];
# endif
CPU_ZERO(&cpuset);
CPU_SET(USE_CPU, &cpuset);
sched_setaffinity(getpid(), sizeof(cpuset), &cpuset);
# if defined(USE_RDTSC)
sprintf(path, "/sys/devices/system/cpu/cpu%i/cpufreq/cpuinfo_max_freq", USE_CPU);
f = fopen(path, "r");
if (getline(&line, &size, f) < 0)
abort();
fclose(f);
freq = strtoull(line, 0, 10);
free(line);
# endif
#endif
(void) timebuf;
}
|