-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathradix_bench.cpp
140 lines (119 loc) · 3.39 KB
/
radix_bench.cpp
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
/*
Sorting benchmark. Requires the google benchmark library.
https://github.com/google/benchmark
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <benchmark/benchmark.h>
#include "radix_sort.hpp"
#include "radix_sort_rank.hpp"
static void* read_file(const char *filename, size_t *limit) {
void *keys = NULL;
size_t bytes = 0;
FILE *f = fopen(filename, "rb");
if (f) {
fseek(f, 0, SEEK_END);
bytes = ftell(f);
fseek(f, 0, SEEK_SET);
if (*limit > 0 && *limit < bytes)
bytes = *limit;
printf("Allocating and reading %zu bytes from '%s'.\n", bytes, filename);
keys = malloc(bytes);
long rnum = fread(keys, bytes, 1, f);
fclose(f);
if (rnum != 1) {
free(keys);
return NULL;
}
}
*limit = bytes;
return keys;
}
template <typename T>
class FileSort : public ::benchmark::Fixture {
public:
typedef T value_type;
static inline void *org_data;
static inline size_t org_size;
void SetUp(const ::benchmark::State& state) {
if (!org_data) {
org_size = 0;
org_data = (T*)read_file("40M_32bit_keys.dat", &org_size);
assert(org_data);
}
this->max_n = org_size / sizeof(T);
this->n = state.range(0);
if (n <= max_n) {
this->src = new T[n];
this->aux = new T[n];
this->aux_rank = new uint32_t[n*2];
std::memcpy(this->src, org_data, sizeof(T) * n);
}
}
void TearDown(const ::benchmark::State& state) {
delete[](this->src);
delete[](this->aux);
delete[](this->aux_rank);
this->src = this->aux = this->aux_rank = NULL;
}
void UpdateCounters(::benchmark::State &state) {
uint64_t keys = state.iterations() * n;
state.counters["KeyRate"] = benchmark::Counter(keys, benchmark::Counter::kIsRate);
state.SetBytesProcessed(keys * sizeof(value_type));
}
T *src;
T *aux;
uint32_t *aux_rank;
size_t n;
size_t max_n;
};
using FSu32 = FileSort<uint32_t>;
BENCHMARK_DEFINE_F(FSu32, radix_sort)(benchmark::State &state) {
if (n > max_n)
state.SkipWithError("Not enough source data to benchmark!");
for (auto _ : state) {
auto *sorted = radix_sort(src, aux, n);
}
UpdateCounters(state);
}
BENCHMARK_DEFINE_F(FSu32, radix_sort_rank)(benchmark::State &state) {
if (n > max_n)
state.SkipWithError("Not enough source data to benchmark!");
auto kf_unsigned = [](const FSu32::value_type& entry) -> FSu32::value_type {
return entry;
};
for (auto _ : state) {
auto *sorted_ranks = radix_sort_rank(src, aux_rank, n, kf_unsigned);
}
UpdateCounters(state);
}
BENCHMARK_DEFINE_F(FSu32, StdSort)(benchmark::State &state) {
if (n > max_n)
state.SkipWithError("Not enough source data to benchmark!");
for (auto _ : state) {
std::sort(src, src + n);
}
UpdateCounters(state);
}
static int qsort_u32(const void *p1, const void *p2) {
uint32_t a = *(const uint32_t*)p1;
uint32_t b = *(const uint32_t*)p2;
if (a < b)
return -1;
return (a > b) ? 1 : 0;
}
BENCHMARK_DEFINE_F(FSu32, QSort)(benchmark::State &state) {
if (n > max_n)
state.SkipWithError("Not enough source data to benchmark!");
for (auto _ : state) {
qsort(src, n, sizeof(*src), qsort_u32);
}
UpdateCounters(state);
}
BENCHMARK_REGISTER_F(FSu32, radix_sort)->RangeMultiplier(10)->Range(1, 40000000);
BENCHMARK_REGISTER_F(FSu32, StdSort)->RangeMultiplier(10)->Range(1, 40000000);
BENCHMARK_REGISTER_F(FSu32, QSort)->RangeMultiplier(10)->Range(1, 40000000);
BENCHMARK_REGISTER_F(FSu32, radix_sort_rank)->RangeMultiplier(10)->Range(1, 40000000);
BENCHMARK_MAIN();