Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Added B+tree multimap for internal (future) use. [#93](https://github.com/tzaeschke/phtree-cpp/issues/93)

### Changed
- Clean up array_map. [#107](https://github.com/tzaeschke/phtree-cpp/issues/107),
- Fixed compatibility with bazel 6.0.0. [#109](https://github.com/tzaeschke/phtree-cpp/issues/109),
- Added missing compiler flag for TZCNT/CTZ (count trailing zeros). This should be much faster on haswell or later CPUs.
[#103](https://github.com/tzaeschke/phtree-cpp/issues/103),
Expand Down
12 changes: 7 additions & 5 deletions benchmark/count_mm_d_benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class IndexBenchmark {
const size_t num_entities_;
const double avg_query_result_size_;

constexpr double query_endge_length() {
constexpr double query_edge_length() {
return GLOBAL_MAX * pow(avg_query_result_size_ / (double)num_entities_, 1. / (double)DIM);
};

Expand Down Expand Up @@ -165,11 +165,13 @@ void IndexBenchmark<DIM, SCENARIO>::QueryWorld(benchmark::State& state, const Qu

template <dimension_t DIM, Scenario SCENARIO>
void IndexBenchmark<DIM, SCENARIO>::CreateQuery(Query& query) {
double radius = query_endge_length() * 0.5;
double length = query_edge_length();
// shift to ensure query lies within boundary
double shift = (GLOBAL_MAX - (double)length) / GLOBAL_MAX;
for (dimension_t d = 0; d < DIM; ++d) {
auto s = cube_distribution_(random_engine_);
query.box.min()[d] = s - radius;
query.box.max()[d] = s + radius;
auto s = shift * cube_distribution_(random_engine_);
query.box.min()[d] = s;
query.box.max()[d] = s + length;
}
}

Expand Down
111 changes: 37 additions & 74 deletions benchmark/find_benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,17 @@ enum QueryType {
/*
* Benchmark for looking up entries by their key.
*/
template <dimension_t DIM>
template <dimension_t DIM, QueryType QUERY_TYPE>
class IndexBenchmark {
public:
IndexBenchmark(
benchmark::State& state, TestGenerator data_type, int num_entities, QueryType query_type);
IndexBenchmark(benchmark::State& state, double dummy);

void Benchmark(benchmark::State& state);

private:
void SetupWorld(benchmark::State& state);
int QueryWorldCount(benchmark::State& state);
int QueryWorldFind(benchmark::State& state);
int QueryWorldCount();
int QueryWorldFind();

const TestGenerator data_type_;
const size_t num_entities_;
Expand All @@ -58,34 +57,33 @@ class IndexBenchmark {
std::vector<PhPoint<DIM>> points_;
};

template <dimension_t DIM>
IndexBenchmark<DIM>::IndexBenchmark(
benchmark::State& state, TestGenerator data_type, int num_entities, QueryType query_type)
: data_type_{data_type}
, num_entities_(num_entities)
, query_type_(query_type)
template <dimension_t DIM, QueryType QUERY_TYPE>
IndexBenchmark<DIM, QUERY_TYPE>::IndexBenchmark(benchmark::State& state, double)
: data_type_{static_cast<TestGenerator>(state.range(1))}
, num_entities_(state.range(0))
, query_type_(QUERY_TYPE)
, random_engine_{1}
, cube_distribution_{0, GLOBAL_MAX}
, points_(num_entities) {
, points_(state.range(0)) {
logging::SetupDefaultLogging();
SetupWorld(state);
}

template <dimension_t DIM>
void IndexBenchmark<DIM>::Benchmark(benchmark::State& state) {
template <dimension_t DIM, QueryType QUERY_TYPE>
void IndexBenchmark<DIM, QUERY_TYPE>::Benchmark(benchmark::State& state) {
int num_inner = 0;
int num_found = 0;
switch (query_type_) {
case COUNT: {
for (auto _ : state) {
num_found += QueryWorldCount(state);
num_found += QueryWorldCount();
++num_inner;
}
break;
}
case FIND: {
for (auto _ : state) {
num_found += QueryWorldFind(state);
num_found += QueryWorldFind();
++num_inner;
}
break;
Expand All @@ -98,8 +96,8 @@ void IndexBenchmark<DIM>::Benchmark(benchmark::State& state) {
state.counters["avg_result_count"] += num_found;
}

template <dimension_t DIM>
void IndexBenchmark<DIM>::SetupWorld(benchmark::State& state) {
template <dimension_t DIM, QueryType QUERY_TYPE>
void IndexBenchmark<DIM, QUERY_TYPE>::SetupWorld(benchmark::State& state) {
logging::info("Setting up world with {} entities and {} dimensions.", num_entities_, DIM);
CreatePointData<DIM>(points_, data_type_, num_entities_, 0, GLOBAL_MAX);
for (size_t i = 0; i < num_entities_; ++i) {
Expand All @@ -110,27 +108,27 @@ void IndexBenchmark<DIM>::SetupWorld(benchmark::State& state) {
state.counters["query_rate"] = benchmark::Counter(0, benchmark::Counter::kIsRate);
state.counters["result_rate"] = benchmark::Counter(0, benchmark::Counter::kIsRate);
state.counters["avg_result_count"] = benchmark::Counter(0, benchmark::Counter::kAvgIterations);

logging::info("World setup complete.");
}

template <dimension_t DIM>
int IndexBenchmark<DIM>::QueryWorldCount(benchmark::State&) {
template <dimension_t DIM, QueryType QUERY_TYPE>
int IndexBenchmark<DIM, QUERY_TYPE>::QueryWorldCount() {
static int pos = 0;
pos = (pos + 1) % num_entities_;
bool found = true;
bool found;
if (pos % 2 == 0) {
assert(tree_.find(points_.at(pos)) != tree_.end());
found = tree_.count(points_.at(pos));
assert(found);
} else {
int x = pos % GLOBAL_MAX;
PhPoint<DIM> p = PhPoint<DIM>({x, x, x});
found = tree_.find(p) != tree_.end();
found = tree_.count(p);
}
return found;
}

template <dimension_t DIM>
int IndexBenchmark<DIM>::QueryWorldFind(benchmark::State&) {
template <dimension_t DIM, QueryType QUERY_TYPE>
int IndexBenchmark<DIM, QUERY_TYPE>::QueryWorldFind() {
static int pos = 0;
pos = (pos + 1) % num_entities_;
bool found;
Expand All @@ -150,61 +148,26 @@ int IndexBenchmark<DIM>::QueryWorldFind(benchmark::State&) {
} // namespace

template <typename... Arguments>
void PhTree3D(benchmark::State& state, Arguments&&... arguments) {
IndexBenchmark<3> benchmark{state, arguments...};
void PhTree3DCount(benchmark::State& state, Arguments&&... arguments) {
IndexBenchmark<3, QueryType::COUNT> benchmark{state, arguments...};
benchmark.Benchmark(state);
}

// index type, scenario name, data_generator, num_entities, function_to_call
// PhTree 3D CUBE
BENCHMARK_CAPTURE(PhTree3D, COUNT_CU_1K, TestGenerator::CUBE, 1000, COUNT)
->Unit(benchmark::kMillisecond);

BENCHMARK_CAPTURE(PhTree3D, COUNT_CU_10K, TestGenerator::CUBE, 10000, COUNT)
->Unit(benchmark::kMillisecond);

BENCHMARK_CAPTURE(PhTree3D, COUNT_CU_100K, TestGenerator::CUBE, 100000, COUNT)
->Unit(benchmark::kMillisecond);

BENCHMARK_CAPTURE(PhTree3D, COUNT_CU_1M, TestGenerator::CUBE, 1000000, COUNT)
->Unit(benchmark::kMillisecond);

BENCHMARK_CAPTURE(PhTree3D, FIND_CU_1K, TestGenerator::CUBE, 1000, FIND)
->Unit(benchmark::kMillisecond);

BENCHMARK_CAPTURE(PhTree3D, FIND_CU_10K, TestGenerator::CUBE, 10000, FIND)
->Unit(benchmark::kMillisecond);

BENCHMARK_CAPTURE(PhTree3D, FIND_CU_100K, TestGenerator::CUBE, 100000, FIND)
->Unit(benchmark::kMillisecond);

BENCHMARK_CAPTURE(PhTree3D, FIND_CU_1M, TestGenerator::CUBE, 1000000, FIND)
->Unit(benchmark::kMillisecond);
template <typename... Arguments>
void PhTree3DFind(benchmark::State& state, Arguments&&... arguments) {
IndexBenchmark<3, QueryType::FIND> benchmark{state, arguments...};
benchmark.Benchmark(state);
}

// index type, scenario name, data_generator, num_entities, function_to_call
// PhTree 3D CLUSTER
BENCHMARK_CAPTURE(PhTree3D, COUNT_CL_1K, TestGenerator::CLUSTER, 1000, COUNT)
->Unit(benchmark::kMillisecond);

BENCHMARK_CAPTURE(PhTree3D, COUNT_CL_10K, TestGenerator::CLUSTER, 10000, COUNT)
->Unit(benchmark::kMillisecond);

BENCHMARK_CAPTURE(PhTree3D, COUNT_CL_100K, TestGenerator::CLUSTER, 100000, COUNT)
->Unit(benchmark::kMillisecond);

BENCHMARK_CAPTURE(PhTree3D, COUNT_CL_1M, TestGenerator::CLUSTER, 1000000, COUNT)
->Unit(benchmark::kMillisecond);

BENCHMARK_CAPTURE(PhTree3D, FIND_CL_1K, TestGenerator::CLUSTER, 1000, FIND)
->Unit(benchmark::kMillisecond);

BENCHMARK_CAPTURE(PhTree3D, FIND_CL_10K, TestGenerator::CLUSTER, 10000, FIND)
->Unit(benchmark::kMillisecond);

BENCHMARK_CAPTURE(PhTree3D, FIND_CL_100K, TestGenerator::CLUSTER, 100000, FIND)
BENCHMARK_CAPTURE(PhTree3DCount, COUNT, 0.0)
->RangeMultiplier(10)
->Ranges({{1000, 1000 * 1000}, {TestGenerator::CUBE, TestGenerator::CLUSTER}})
->Unit(benchmark::kMillisecond);

BENCHMARK_CAPTURE(PhTree3D, FIND_CL_1M, TestGenerator::CLUSTER, 1000000, FIND)
BENCHMARK_CAPTURE(PhTree3DFind, FIND, 0.0)
->RangeMultiplier(10)
->Ranges({{1000, 1000 * 1000}, {TestGenerator::CUBE, TestGenerator::CLUSTER}})
->Unit(benchmark::kMillisecond);

BENCHMARK_MAIN();
11 changes: 5 additions & 6 deletions benchmark/query_benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class IndexBenchmark {
const size_t num_entities_;
const double avg_query_result_size_;

constexpr int query_endge_length() {
constexpr int query_edge_length() {
return (
int)(GLOBAL_MAX * pow(avg_query_result_size_ / (double)num_entities_, 1. / (double)DIM));
};
Expand Down Expand Up @@ -110,12 +110,11 @@ void IndexBenchmark<DIM>::QueryWorld(benchmark::State& state, PhBox<DIM>& query_

template <dimension_t DIM>
void IndexBenchmark<DIM>::CreateQuery(PhBox<DIM>& query_box) {
int length = query_endge_length();
// scale to ensure query lies within boundary
double scale = (GLOBAL_MAX - (double)length) / GLOBAL_MAX;
int length = query_edge_length();
// shift to ensure query lies within boundary
double shift = (GLOBAL_MAX - (double)length) / GLOBAL_MAX;
for (dimension_t d = 0; d < DIM; ++d) {
scalar_64_t s = cube_distribution_(random_engine_);
s = (scalar_64_t)(s * scale);
scalar_64_t s = (scalar_64_t)(shift * cube_distribution_(random_engine_));
query_box.min()[d] = s;
query_box.max()[d] = s + length;
}
Expand Down
10 changes: 5 additions & 5 deletions benchmark/query_box_d_benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class IndexBenchmark {
const size_t num_entities_;
const double avg_query_result_size_;

constexpr int query_endge_length() {
constexpr int query_edge_length() {
return (
int)(GLOBAL_MAX * pow(avg_query_result_size_ / (double)num_entities_, 1. / (double)DIM));
};
Expand Down Expand Up @@ -153,12 +153,12 @@ void IndexBenchmark<DIM, QUERY_TYPE>::QueryWorld(benchmark::State& state, BoxTyp

template <dimension_t DIM, QueryType QUERY_TYPE>
void IndexBenchmark<DIM, QUERY_TYPE>::CreateQuery(BoxType<DIM>& query_box) {
int length = query_endge_length();
int length = query_edge_length();
// scale to ensure query lies within boundary
double scale = (GLOBAL_MAX - (double)length) / GLOBAL_MAX;
double shift = (GLOBAL_MAX - (double)length) / GLOBAL_MAX;
for (dimension_t d = 0; d < DIM; ++d) {
auto s = cube_distribution_(random_engine_);
s = s * scale;
auto s = shift * cube_distribution_(random_engine_);
s = s * shift;
query_box.min()[d] = s;
query_box.max()[d] = s + length;
}
Expand Down
11 changes: 5 additions & 6 deletions benchmark/query_d_benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class IndexBenchmark {
const size_t num_entities_;
const double avg_query_result_size_;

constexpr int query_endge_length() {
constexpr int query_edge_length() {
return (
int)(GLOBAL_MAX * pow(avg_query_result_size_ / (double)num_entities_, 1. / (double)DIM));
};
Expand Down Expand Up @@ -152,12 +152,11 @@ void IndexBenchmark<DIM, QUERY_TYPE>::QueryWorld(benchmark::State& state, BoxTyp

template <dimension_t DIM, QueryType QUERY_TYPE>
void IndexBenchmark<DIM, QUERY_TYPE>::CreateQuery(BoxType<DIM>& query_box) {
int length = query_endge_length();
// scale to ensure query lies within boundary
double scale = (GLOBAL_MAX - (double)length) / GLOBAL_MAX;
int length = query_edge_length();
// shift to ensure query lies within boundary
double shift = (GLOBAL_MAX - (double)length) / GLOBAL_MAX;
for (dimension_t d = 0; d < DIM; ++d) {
auto s = cube_distribution_(random_engine_);
s = s * scale;
auto s = shift * cube_distribution_(random_engine_);
query_box.min()[d] = s;
query_box.max()[d] = s + length;
}
Expand Down
12 changes: 7 additions & 5 deletions benchmark/query_mm_box_d_benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class IndexBenchmark {
const size_t num_entities_;
const double avg_query_result_size_;

constexpr double query_endge_length() {
constexpr double query_edge_length() {
return GLOBAL_MAX * pow(avg_query_result_size_ / (double)num_entities_, 1. / (double)DIM);
};

Expand Down Expand Up @@ -184,11 +184,13 @@ void IndexBenchmark<DIM, SCENARIO>::QueryWorld(benchmark::State& state, const Qu

template <dimension_t DIM, Scenario SCENARIO>
void IndexBenchmark<DIM, SCENARIO>::CreateQuery(Query& query) {
double radius = query_endge_length() * 0.5;
double length = query_edge_length();
// shift to ensure query lies within boundary
double shift = (GLOBAL_MAX - (double)length) / GLOBAL_MAX;
for (dimension_t d = 0; d < DIM; ++d) {
auto x = cube_distribution_(random_engine_);
query.box_.min()[d] = x - radius;
query.box_.max()[d] = x + radius;
auto x = shift * cube_distribution_(random_engine_);
query.box_.min()[d] = x;
query.box_.max()[d] = x + length;
}
}

Expand Down
Loading