-
Notifications
You must be signed in to change notification settings - Fork 0
/
benchmark.cc
159 lines (131 loc) · 4.36 KB
/
benchmark.cc
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
147
148
149
150
151
152
153
154
155
156
157
158
#include <cassert>
#include <chrono>
#include <functional>
#include <iostream>
#include <random>
#include <vector>
#include "multi.h"
#include "mvn.h"
#include "relles.h"
#include "vose.h"
#include "we.h"
template<class C>
static void polya_test(int n, int m) {
std::vector<uint64_t> dist(m, 1);
C generator(dist);
for (int i = 0; i < n; i ++) {
int r = generator.sample();
generator.delta_update(r, 1);
}
}
template<class C>
static void static_test(int n, int m) {
std::vector<uint64_t> dist(m);
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_int_distribution<> intd(0, m - 1);
for (int i = 0; i < m; i ++)
dist[i] = intd(mt);
C generator(dist);
for (int i = 0; i < n; i ++) {
generator.sample();
}
}
template<class C>
static void without_replacement_test(int n, int m) {
assert(n / m * m == n);
std::vector<uint64_t> dist(m, n / m);
C generator(dist);
for (int i = 0; i < n; i ++) {
int r = generator.sample();
generator.delta_update(r, -1);
}
}
template<class C>
static void random_test(int n, int m, double k) {
std::vector<uint64_t> dist(m, 1);
std::random_device rd;
std::mt19937 mt(rd());
std::bernoulli_distribution action(k);
std::uniform_int_distribution<> intd(0, m - 1);
C generator(dist);
for (int i = 0; i < n; i ++) {
if (action(mt)) {
generator.update(intd(mt), intd(mt));
} else {
generator.sample();
}
}
}
static void multinomial_test(int n, int k, std::function<std::vector<uint64_t>(uint64_t n, const std::vector<long double>&)> func) {
std::vector<long double> dist(k);
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_real_distribution<> unif(0, 1);
double total = 0;
for (int i = 0; i < k; i ++) {
dist[i] = unif(mt);
total += dist[i];
}
for (int i = 0; i < k; i ++)
dist[i] /= total;
func(n, dist);
}
template<class F, class ...Args>
static double benchmark(int n, F& func, Args&& ...args) {
auto begin = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; i ++)
func(args...);
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> secs = end - begin;
return secs.count() / n;
}
static void multinomial_battery() {
int a = 10;
std::vector<int> ks = { 10, 100000 };
for (int k : ks) {
for (uint64_t n = 10; n <= 100000000000; n *= 10) {
std::cout << "k = " << k << ", n = " << n << "\n";
std::cout << " BTPE " << benchmark(a, multinomial_test, n, k, btpe) << "\n";
std::cout << " Relles " << benchmark(a, multinomial_test, n, k, relles) << "\n";
std::cout << " Relles enhanced " << benchmark(a, multinomial_test, n, k, relles_enhanced) << "\n";
}
}
std::cout << "" << "\n";
}
static void categorical_battery() {
int n = 50;
for (int i = 10; i <= 1000000; i *= 10) {
int m = i;
std::cout << m << ":\n";
std::cout << " Static WE " << benchmark(n, static_test<we>, 1000000, m) << "\n";
std::cout << " Static MVN " << benchmark(n, static_test<mvn>, 1000000, m) << "\n";
std::cout << " Static Vose " << benchmark(n, static_test<vose>, 1000000, m) << "\n";
}
for (int i = 10; i <= 1000; i *= 10) {
int m = i;
std::cout << m << ":\n";
std::cout << " Polya WE " << benchmark(n, polya_test<we>, 1000000, m) << "\n";
std::cout << " Polya MVN " << benchmark(n, polya_test<mvn>, 1000000, m) << "\n";
std::cout << " Polya Vose " << benchmark(5, polya_test<vose>, 1000000, m) << "\n";
}
for (int i = 10; i <= 1000; i *= 10) {
int m = i;
std::cout << m << ":\n";
std::cout << " Without Replacement WE " << benchmark(n, without_replacement_test<we>, 1000000, m) << "\n";
std::cout << " Without Replacement MVN " << benchmark(n, without_replacement_test<mvn>, 1000000, m) << "\n";
std::cout << " Without Replacement Vose " << benchmark(5, without_replacement_test<vose>, 1000000, m) << "\n";
}
for (int i = 10; i <= 1000; i *= 10) {
int m = i;
std::cout << m << ":\n";
std::cout << " Random (k = 0.1) WE " << benchmark(n, random_test<we>, 1000000, m, 0.1) << "\n";
std::cout << " Random (k = 0.1) MVN " << benchmark(n, random_test<mvn>, 1000000, m, 0.1) << "\n";
std::cout << " Random (k = 0.1) Vose " << benchmark(5, random_test<vose>, 1000000, m, 0.1) << "\n";
}
}
int main(int argc, char **argv) {
multinomial_battery();
categorical_battery();
return 0;
}