Skip to content

Commit 8deadd7

Browse files
committed
squash 5
1 parent d3c8eac commit 8deadd7

17 files changed

+1696
-33
lines changed

benchmark/BUILD

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,21 @@ cc_binary(
232232
],
233233
)
234234

235+
cc_binary(
236+
name = "knn_mm_d_benchmark",
237+
testonly = True,
238+
srcs = [
239+
"knn_mm_d_benchmark.cc",
240+
],
241+
linkstatic = True,
242+
deps = [
243+
":benchmark",
244+
"//:phtree",
245+
"@gbenchmark//:benchmark",
246+
"@spdlog",
247+
],
248+
)
249+
235250
cc_binary(
236251
name = "query_benchmark",
237252
testonly = True,

benchmark/bpt_insert_benchmark.cc

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "benchmark_util.h"
1717
#include "logging.h"
1818
#include "phtree/common/b_plus_tree_hash_map.h"
19+
#include "phtree/common/b_plus_tree_heap.h"
1920
#include "phtree/common/b_plus_tree_map.h"
2021
#include "phtree/common/b_plus_tree_multimap.h"
2122
#include <benchmark/benchmark.h>
@@ -31,6 +32,7 @@ const int GLOBAL_MAX = 10000;
3132
enum Scenario {
3233
MAP,
3334
MULTIMAP,
35+
MULTIMAP2,
3436
HASH_MAP,
3537
STD_MAP,
3638
STD_MULTIMAP,
@@ -55,7 +57,10 @@ using TestIndex = typename std::conditional_t<
5557
typename std::conditional_t<
5658
SCENARIO == STD_MULTIMAP,
5759
std::multimap<key_t, payload_t>,
58-
void>>>>>;
60+
typename std::conditional_t<
61+
SCENARIO == MULTIMAP2,
62+
b_plus_tree_multimap2<key_t, payload_t>,
63+
void>>>>>>;
5964

6065
/*
6166
* Benchmark for adding entries to the index.
@@ -117,7 +122,22 @@ void IndexBenchmark<DIM, TYPE>::SetupWorld(benchmark::State& state) {
117122
template <dimension_t DIM, Scenario TYPE>
118123
void IndexBenchmark<DIM, TYPE>::Insert(benchmark::State& state, Index& tree) {
119124
switch (TYPE) {
120-
default: {
125+
case MAP: {
126+
for (size_t i = 0; i < num_entities_; ++i) {
127+
tree.emplace(points_[i][0], (payload_t)i);
128+
}
129+
break;
130+
}
131+
case MULTIMAP:
132+
case MULTIMAP2:
133+
case STD_MULTIMAP: {
134+
for (size_t i = 0; i < num_entities_; ++i) {
135+
tree.emplace(points_[i][0], (payload_t)i);
136+
}
137+
break;
138+
}
139+
case HASH_MAP:
140+
case STD_MAP: {
121141
for (size_t i = 0; i < num_entities_; ++i) {
122142
tree.emplace(points_[i][0], (payload_t)i);
123143
}
@@ -161,6 +181,12 @@ void BPT_MM_INS(benchmark::State& state, Arguments&&... arguments) {
161181
benchmark.Benchmark(state);
162182
}
163183

184+
template <typename... Arguments>
185+
void BPT_MM2_INS(benchmark::State& state, Arguments&&... arguments) {
186+
IndexBenchmark<3, MULTIMAP2> benchmark{state, arguments...};
187+
benchmark.Benchmark(state);
188+
}
189+
164190
template <typename... Arguments>
165191
void BPT_HM_INS(benchmark::State& state, Arguments&&... arguments) {
166192
IndexBenchmark<3, HASH_MAP> benchmark{state, arguments...};
@@ -205,6 +231,11 @@ BENCHMARK_CAPTURE(BPT_MM_INS, MULTIMAP, 0.0)
205231
->Ranges({{100, 100 * 1000}, {TestGenerator::CLUSTER, TestGenerator::CUBE}})
206232
->Unit(benchmark::kMillisecond);
207233

234+
BENCHMARK_CAPTURE(BPT_MM2_INS, MULTIMAP2, 0.0)
235+
->RangeMultiplier(10)
236+
->Ranges({{100, 100 * 1000}, {TestGenerator::CLUSTER, TestGenerator::CUBE}})
237+
->Unit(benchmark::kMillisecond);
238+
208239
BENCHMARK_CAPTURE(BPT_HM_INS, HASH_MAP, 0.0)
209240
->RangeMultiplier(10)
210241
->Ranges({{100, 100 * 1000}, {TestGenerator::CLUSTER, TestGenerator::CUBE}})

benchmark/hd_erase_d_benchmark.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ using payload_t = std::uint32_t;
3434
template <dimension_t DIM>
3535
class IndexBenchmark {
3636
public:
37-
IndexBenchmark(benchmark::State& state);
37+
explicit IndexBenchmark(benchmark::State& state);
3838
void Benchmark(benchmark::State& state);
3939

4040
private:

benchmark/knn_mm_d_benchmark.cc

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
/*
2+
* Copyright 2020 Improbable Worlds Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include "benchmark_util.h"
17+
#include "logging.h"
18+
#include "phtree/phtree.h"
19+
#include "phtree/phtree_multimap.h"
20+
#include <benchmark/benchmark.h>
21+
#include <random>
22+
23+
using namespace improbable;
24+
using namespace improbable::phtree;
25+
using namespace improbable::phtree::phbenchmark;
26+
27+
/*
28+
* Benchmark for k-nearest-neighbour queries in multi-map implementations.
29+
*/
30+
namespace {
31+
32+
const double GLOBAL_MAX = 10000;
33+
const dimension_t DIM = 3;
34+
35+
enum Scenario {
36+
TREE_SET,
37+
PHTREE_MM,
38+
PHTREE_MM_STD,
39+
PHTREE2,
40+
TS_KD,
41+
TS_QT,
42+
};
43+
44+
using payload_t = int64_t;
45+
using payload2_t = uint32_t;
46+
47+
using TestPoint = PhPointD<DIM>;
48+
using QueryBox = PhBoxD<DIM>;
49+
using BucketType = std::set<payload_t>;
50+
51+
template <dimension_t DIM>
52+
using CONVERTER = ConverterIEEE<DIM>;
53+
54+
template <Scenario SCENARIO, dimension_t DIM>
55+
using TestMap = typename std::conditional_t<
56+
SCENARIO == TREE_SET,
57+
PhTreeD<DIM, BucketType, CONVERTER<DIM>>,
58+
typename std::conditional_t<
59+
SCENARIO == PHTREE_MM,
60+
PhTreeMultiMap<DIM, payload_t, CONVERTER<DIM>, b_plus_tree_hash_set<payload_t>>,
61+
// typename std::conditional_t<
62+
// SCENARIO == PHTREE2,
63+
// PhTreeMultiMap2D<DIM, payload_t>,
64+
typename std::conditional_t<
65+
SCENARIO == PHTREE_MM_STD,
66+
PhTreeMultiMap<DIM, payload_t, CONVERTER<DIM>, BucketType>,
67+
void>>>;
68+
69+
template <dimension_t DIM, Scenario SCENARIO>
70+
class IndexBenchmark {
71+
public:
72+
IndexBenchmark(benchmark::State& state, int knn_result_size_);
73+
74+
void Benchmark(benchmark::State& state);
75+
76+
private:
77+
void SetupWorld(benchmark::State& state);
78+
void QueryWorld(benchmark::State& state, TestPoint& center);
79+
void CreateQuery(TestPoint& center);
80+
81+
const TestGenerator data_type_;
82+
const size_t num_entities_;
83+
const size_t knn_result_size_;
84+
85+
TestMap<SCENARIO, DIM> tree_;
86+
std::default_random_engine random_engine_;
87+
std::uniform_real_distribution<> cube_distribution_;
88+
std::vector<TestPoint> points_;
89+
};
90+
91+
template <dimension_t DIM, Scenario SCENARIO>
92+
IndexBenchmark<DIM, SCENARIO>::IndexBenchmark(benchmark::State& state, int knn_result_size)
93+
: data_type_{static_cast<TestGenerator>(state.range(1))}
94+
, num_entities_(state.range(0))
95+
, knn_result_size_(knn_result_size)
96+
, random_engine_{1}
97+
, cube_distribution_{0, GLOBAL_MAX}
98+
, points_(state.range(0)) {
99+
logging::SetupDefaultLogging();
100+
SetupWorld(state);
101+
}
102+
103+
template <dimension_t DIM, Scenario SCENARIO>
104+
void IndexBenchmark<DIM, SCENARIO>::Benchmark(benchmark::State& state) {
105+
for (auto _ : state) {
106+
state.PauseTiming();
107+
TestPoint center;
108+
CreateQuery(center);
109+
state.ResumeTiming();
110+
111+
QueryWorld(state, center);
112+
}
113+
}
114+
115+
template <
116+
dimension_t DIM,
117+
Scenario SCENARIO,
118+
std::enable_if_t<(SCENARIO == Scenario::TREE_SET), int> = 0>
119+
void InsertEntries(TestMap<Scenario::TREE_SET, DIM>& tree, const std::vector<TestPoint>& points) {
120+
for (size_t i = 0; i < points.size(); ++i) {
121+
BucketType& bucket = tree.emplace(points[i]).first;
122+
bucket.emplace((payload_t)i);
123+
}
124+
}
125+
126+
template <dimension_t DIM, Scenario SCN, std::enable_if_t<(SCN != Scenario::TREE_SET), int> = 0>
127+
void InsertEntries(TestMap<SCN, DIM>& tree, const std::vector<TestPoint>& points) {
128+
for (size_t i = 0; i < points.size(); ++i) {
129+
tree.emplace(points[i], (payload_t)i);
130+
}
131+
}
132+
133+
template <dimension_t DIM, Scenario SCN>
134+
size_t QueryAll(TestMap<SCN, DIM>& tree, const TestPoint& center, const size_t k) {
135+
size_t n = 0;
136+
for (auto q = tree.begin_knn_query(k, center, DistanceEuclidean<DIM>()); q != tree.end(); ++q) {
137+
++n;
138+
}
139+
return n;
140+
}
141+
142+
struct CounterTreeWithMap {
143+
void operator()(const TestPoint&, const BucketType& value) {
144+
for (auto& x : value) {
145+
(void)x;
146+
n_ += 1;
147+
}
148+
}
149+
size_t n_;
150+
};
151+
152+
struct CounterMultiMap {
153+
void operator()(const TestPoint&, const payload_t&) {
154+
n_ += 1;
155+
}
156+
size_t n_;
157+
};
158+
159+
template <dimension_t DIM, Scenario SCENARIO>
160+
void IndexBenchmark<DIM, SCENARIO>::SetupWorld(benchmark::State& state) {
161+
logging::info("Setting up world with {} entities and {} dimensions.", num_entities_, DIM);
162+
CreatePointData<DIM>(points_, data_type_, num_entities_, 0, GLOBAL_MAX);
163+
InsertEntries<DIM, SCENARIO>(tree_, points_);
164+
165+
state.counters["query_rate"] = benchmark::Counter(0, benchmark::Counter::kIsRate);
166+
state.counters["result_rate"] = benchmark::Counter(0, benchmark::Counter::kIsRate);
167+
state.counters["avg_result_count"] = benchmark::Counter(0, benchmark::Counter::kAvgIterations);
168+
logging::info("World setup complete.");
169+
}
170+
171+
template <dimension_t DIM, Scenario SCENARIO>
172+
void IndexBenchmark<DIM, SCENARIO>::QueryWorld(benchmark::State& state, TestPoint& center) {
173+
size_t n = QueryAll<DIM, SCENARIO>(tree_, center, knn_result_size_);
174+
175+
state.counters["query_rate"] += 1;
176+
state.counters["result_rate"] += n;
177+
state.counters["avg_result_count"] += n;
178+
}
179+
180+
template <dimension_t DIM, Scenario SCENARIO>
181+
void IndexBenchmark<DIM, SCENARIO>::CreateQuery(TestPoint& center) {
182+
for (dimension_t d = 0; d < DIM; ++d) {
183+
center[d] = cube_distribution_(random_engine_) * GLOBAL_MAX;
184+
}
185+
}
186+
187+
} // namespace
188+
189+
// template <typename... Arguments>
190+
// void TinspinKDTree(benchmark::State& state, Arguments&&... arguments) {
191+
// IndexBenchmark<DIM, Scenario::TS_KD> benchmark{state, arguments...};
192+
// benchmark.Benchmark(state);
193+
// }
194+
//
195+
// template <typename... Arguments>
196+
// void TinspinQuadtree(benchmark::State& state, Arguments&&... arguments) {
197+
// IndexBenchmark<DIM, Scenario::TS_QT> benchmark{state, arguments...};
198+
// benchmark.Benchmark(state);
199+
// }
200+
201+
template <typename... Arguments>
202+
void PhTree3D(benchmark::State& state, Arguments&&... arguments) {
203+
IndexBenchmark<DIM, Scenario::TREE_SET> benchmark{state, arguments...};
204+
benchmark.Benchmark(state);
205+
}
206+
207+
template <typename... Arguments>
208+
void PhTreeMM(benchmark::State& state, Arguments&&... arguments) {
209+
IndexBenchmark<DIM, Scenario::PHTREE_MM> benchmark{state, arguments...};
210+
benchmark.Benchmark(state);
211+
}
212+
213+
//template <typename... Arguments>
214+
//void PhTreeMM2(benchmark::State& state, Arguments&&... arguments) {
215+
// IndexBenchmark<DIM, Scenario::PHTREE2> benchmark{state, arguments...};
216+
// benchmark.Benchmark(state);
217+
//}
218+
219+
template <typename... Arguments>
220+
void PhTreeMMStdSet(benchmark::State& state, Arguments&&... arguments) {
221+
IndexBenchmark<DIM, Scenario::PHTREE_MM_STD> benchmark{state, arguments...};
222+
benchmark.Benchmark(state);
223+
}
224+
225+
// index type, scenario name, data_type, num_entities, query_result_size
226+
227+
// PhTree multi-map 1.0
228+
BENCHMARK_CAPTURE(PhTreeMM, KNN_1, 1)
229+
->RangeMultiplier(10)
230+
->Ranges({{1000, 1000 * 1000}, {TestGenerator::CUBE, TestGenerator::CLUSTER}})
231+
->Unit(benchmark::kMillisecond);
232+
233+
BENCHMARK_CAPTURE(PhTreeMM, KNN_10, 10)
234+
->RangeMultiplier(10)
235+
->Ranges({{1000, 1000 * 1000}, {TestGenerator::CUBE, TestGenerator::CLUSTER}})
236+
->Unit(benchmark::kMillisecond);
237+
238+
//// Multimap 2.0
239+
//BENCHMARK_CAPTURE(PhTreeMM2, KNN_1, 1)
240+
// ->RangeMultiplier(10)
241+
// ->Ranges({{1000, 1000 * 1000}, {TestGenerator::CUBE, TestGenerator::CLUSTER}})
242+
// ->Unit(benchmark::kMillisecond);
243+
//
244+
//BENCHMARK_CAPTURE(PhTreeMM2, KNN_10, 10)
245+
// ->RangeMultiplier(10)
246+
// ->Ranges({{1000, 1000 * 1000}, {TestGenerator::CUBE, TestGenerator::CLUSTER}})
247+
// ->Unit(benchmark::kMillisecond);
248+
249+
//// KD-tree
250+
// BENCHMARK_CAPTURE(TinspinKDTree, KNN_1, 1)
251+
// ->RangeMultiplier(10)
252+
// ->Ranges({{1000, 1000 * 1000}, {TestGenerator::CUBE, TestGenerator::CLUSTER}})
253+
// ->Unit(benchmark::kMillisecond);
254+
//
255+
// BENCHMARK_CAPTURE(TinspinKDTree, KNN_10, 10)
256+
// ->RangeMultiplier(10)
257+
// ->Ranges({{1000, 1000 * 1000}, {TestGenerator::CUBE, TestGenerator::CLUSTER}})
258+
// ->Unit(benchmark::kMillisecond);
259+
//
260+
//// Quadtree
261+
// BENCHMARK_CAPTURE(TinspinQuadtree, KNN_1, 1)
262+
// ->RangeMultiplier(10)
263+
// ->Ranges({{1000, 1000 * 1000}, {TestGenerator::CUBE, TestGenerator::CLUSTER}})
264+
// ->Unit(benchmark::kMillisecond);
265+
//
266+
// BENCHMARK_CAPTURE(TinspinQuadtree, KNN_10, 10)
267+
// ->RangeMultiplier(10)
268+
// ->Ranges({{1000, 1000 * 1000}, {TestGenerator::CUBE, TestGenerator::CLUSTER}})
269+
// ->Unit(benchmark::kMillisecond);
270+
271+
// PhTree 3D with set
272+
BENCHMARK_CAPTURE(PhTree3D, KNN_1, 1)
273+
->RangeMultiplier(10)
274+
->Ranges({{1000, 1000 * 1000}, {TestGenerator::CUBE, TestGenerator::CLUSTER}})
275+
->Unit(benchmark::kMillisecond);
276+
277+
BENCHMARK_CAPTURE(PhTree3D, KNN_10, 10)
278+
->RangeMultiplier(10)
279+
->Ranges({{1000, 1000 * 1000}, {TestGenerator::CUBE, TestGenerator::CLUSTER}})
280+
->Unit(benchmark::kMillisecond);
281+
282+
BENCHMARK_MAIN();

include/phtree/common/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ cc_library(
55
hdrs = [
66
"b_plus_tree_base.h",
77
"b_plus_tree_hash_map.h",
8+
"b_plus_tree_heap.h",
89
"b_plus_tree_map.h",
910
"b_plus_tree_multimap.h",
1011
"base_types.h",

0 commit comments

Comments
 (0)