Skip to content

Commit d00aa3a

Browse files
committed
refactor(repository): remove repository from the lib and move into benchmark
1 parent 615ccea commit d00aa3a

57 files changed

Lines changed: 2701 additions & 2635 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.clang-format‎

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
---
2+
Language: Cpp
3+
# BasedOnStyle: Google
4+
AccessModifierOffset: -2
5+
AlignAfterOpenBracket: Align
6+
AlignConsecutiveAssignments: false
7+
AlignConsecutiveDeclarations: false
8+
AlignEscapedNewlinesLeft: true
9+
AlignOperands: true
10+
AlignTrailingComments: true
11+
AllowAllParametersOfDeclarationOnNextLine: true
12+
AllowShortBlocksOnASingleLine: false
13+
AllowShortCaseLabelsOnASingleLine: false
14+
AllowShortFunctionsOnASingleLine: All
15+
AllowShortIfStatementsOnASingleLine: true
16+
AllowShortLoopsOnASingleLine: true
17+
AlwaysBreakAfterDefinitionReturnType: None
18+
AlwaysBreakAfterReturnType: None
19+
AlwaysBreakBeforeMultilineStrings: true
20+
AlwaysBreakTemplateDeclarations: true
21+
BinPackArguments: true
22+
BinPackParameters: true
23+
BraceWrapping:
24+
AfterClass: false
25+
AfterControlStatement: false
26+
AfterEnum: false
27+
AfterFunction: false
28+
AfterNamespace: false
29+
AfterObjCDeclaration: false
30+
AfterStruct: false
31+
AfterUnion: false
32+
BeforeCatch: false
33+
BeforeElse: false
34+
IndentBraces: false
35+
BreakBeforeBinaryOperators: None
36+
BreakBeforeBraces: Allman
37+
BreakBeforeTernaryOperators: true
38+
BreakConstructorInitializersBeforeComma: false
39+
ColumnLimit: 120
40+
CommentPragmas: '^ IWYU pragma:'
41+
ConstructorInitializerAllOnOneLineOrOnePerLine: true
42+
ConstructorInitializerIndentWidth: 4
43+
ContinuationIndentWidth: 4
44+
Cpp11BracedListStyle: true
45+
DerivePointerAlignment: false
46+
DisableFormat: false
47+
ExperimentalAutoDetectBinPacking: false
48+
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
49+
SortIncludes: true
50+
IncludeBlocks: Regroup
51+
IncludeCategories:
52+
# Headers in <> without extension.
53+
- Regex: '<([A-Za-z0-9\Q/-_\E])+>'
54+
Priority: 3
55+
# Headers in <> with extension.
56+
- Regex: '<([A-Za-z0-9.\Q/-_\E])+>'
57+
Priority: 2
58+
# Headers in "" with extension.
59+
- Regex: '"([A-Za-z0-9.\Q/-_\E])+"'
60+
Priority: 1
61+
- Regex: '.*'
62+
Priority: 0
63+
IndentCaseLabels: true
64+
IndentWidth: 4
65+
IndentWrappedFunctionNames: false
66+
KeepEmptyLinesAtTheStartOfBlocks: false
67+
MacroBlockBegin: ''
68+
MacroBlockEnd: ''
69+
MaxEmptyLinesToKeep: 1
70+
NamespaceIndentation: None
71+
ObjCBlockIndentWidth: 2
72+
ObjCSpaceAfterProperty: false
73+
ObjCSpaceBeforeProtocolList: false
74+
PenaltyBreakBeforeFirstCallParameter: 1
75+
PenaltyBreakComment: 300
76+
PenaltyBreakFirstLessLess: 120
77+
PenaltyBreakString: 1000
78+
PenaltyExcessCharacter: 1000000
79+
PenaltyReturnTypeOnItsOwnLine: 200
80+
PointerAlignment: Left
81+
ReflowComments: true
82+
SpaceAfterCStyleCast: false
83+
SpaceBeforeAssignmentOperators: true
84+
SpaceBeforeParens: ControlStatements
85+
SpaceInEmptyParentheses: false
86+
SpacesBeforeTrailingComments: 2
87+
SpacesInAngles: false
88+
SpacesInContainerLiterals: true
89+
SpacesInCStyleCastParentheses: false
90+
SpacesInParentheses: false
91+
SpacesInSquareBrackets: false
92+
Standard: Cpp11
93+
TabWidth: 8
94+
UseTab: Never
95+
---
96+
Language: Proto

‎cpp/bench/include/benchmark.h‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ static float test_approx_anns(const deglib::graph::InternalGraph& graph,
9898
const auto& gt = ground_truth[i];
9999
while (result_queue.empty() == false) {
100100
const auto& result = result_queue.top();
101-
const auto external_id = graph.getExternalLabel(result.getInternalIndex());
101+
const auto external_id = graph.getExternalLabel(result.getIdentifier());
102102
if (std::binary_search(gt.begin(), gt.end(), external_id)) correct++;
103103
result_queue.pop();
104104
}
@@ -138,7 +138,7 @@ static float test_approx_explore(const deglib::graph::InternalGraph& graph,
138138
const auto& gt = ground_truth[i];
139139
while (result_queue.empty() == false) {
140140
const auto& result = result_queue.top();
141-
const auto external_id = graph.getExternalLabel(result.getInternalIndex());
141+
const auto external_id = graph.getExternalLabel(result.getIdentifier());
142142
if (std::binary_search(gt.begin(), gt.end(), external_id)) correct++;
143143
result_queue.pop();
144144
}
@@ -175,7 +175,7 @@ static std::vector<float> estimate_recall(const deglib::graph::InternalGraph& gr
175175

176176
size_t local_correct = 0;
177177
while (result_queue.empty() == false) {
178-
const auto internal_index = result_queue.top().getInternalIndex();
178+
const auto internal_index = result_queue.top().getIdentifier();
179179
const auto external_id = graph.getExternalLabel(internal_index);
180180
if (std::binary_search(gt.begin(), gt.end(), external_id)) local_correct++;
181181
result_queue.pop();

‎cpp/bench/include/dataset.h‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <vector>
2323

2424
#include <deglib/deglib.h>
25+
#include "repository.h"
2526
#include "file_io.h"
2627

2728
namespace deglib::benchmark {
@@ -303,7 +304,7 @@ inline std::vector<uint32_t> compute_knn_groundtruth(const deglib::FeatureReposi
303304
auto topList = topLists.data() + (k_target * q);
304305
for (int32_t i = k_target - 1; i >= 0; i--) {
305306
if (!results.empty()) {
306-
topList[i] = results.top().getInternalIndex();
307+
topList[i] = results.top().getIdentifier();
307308
results.pop();
308309
} else {
309310
topList[i] = (std::numeric_limits<uint32_t>::max)();

‎cpp/benchmark/include/benchmark.h‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <span>
1010

1111
#include <deglib/deglib.h>
12+
#include "repository.h"
1213
#include "stopwatch.h"
1314

1415
namespace deglib::benchmark
@@ -54,7 +55,7 @@ static float test_approx_anns(const deglib::graph::InternalGraph& graph, const s
5455
while (result_queue.empty() == false)
5556
{
5657
const auto& result = result_queue.top();
57-
const auto external_id = graph.getExternalLabel(result.getInternalIndex());
58+
const auto external_id = graph.getExternalLabel(result.getIdentifier());
5859
if (gt.find(external_id) != gt.end()) correct++;
5960
result_queue.pop();
6061
}
@@ -89,7 +90,7 @@ static float test_approx_explore(const deglib::graph::InternalGraph& graph, cons
8990
while (result_queue.empty() == false)
9091
{
9192
const auto& result = result_queue.top();
92-
const auto external_id = graph.getExternalLabel(result.getInternalIndex());
93+
const auto external_id = graph.getExternalLabel(result.getIdentifier());
9394
if (gt.find(external_id) != gt.end()) correct++;
9495
result_queue.pop();
9596
}

‎cpp/benchmark/include/repository.h‎

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
#pragma once
2+
3+
#include <assert.h>
4+
#include <stdio.h>
5+
#include <cstring>
6+
#include <unordered_map>
7+
8+
#include <filesystem>
9+
#include <fstream>
10+
#include <iostream>
11+
12+
namespace deglib
13+
{
14+
/**
15+
* A repository of float feature vectors.
16+
*/
17+
class FeatureRepository
18+
{
19+
public:
20+
virtual size_t dims() const = 0;
21+
virtual size_t size() const = 0;
22+
virtual const std::byte* getFeature(const uint32_t vertexid) const = 0;
23+
virtual void clear() = 0;
24+
};
25+
26+
/**
27+
* A repository of float feature vectors. Since the repository deals
28+
* with static data, a single contiguous array is preserved internally.
29+
*/
30+
class StaticFeatureRepository : public FeatureRepository
31+
{
32+
public:
33+
StaticFeatureRepository(std::unique_ptr<std::byte[]> contiguous_features, const size_t dims, const size_t count, const size_t bytes_per_dim)
34+
: bytes_per_dim_{bytes_per_dim}, dims_{dims}, count_{count}, contiguous_features_{std::move(contiguous_features), }
35+
{
36+
}
37+
38+
size_t dims() const override { return dims_; }
39+
size_t size() const override { return count_; }
40+
const std::byte* getFeature(const uint32_t idx) const override { return &contiguous_features_[idx * dims_ * bytes_per_dim_]; }
41+
void clear() override { contiguous_features_.reset(); }
42+
43+
private:
44+
const size_t bytes_per_dim_;
45+
const size_t dims_;
46+
const size_t count_;
47+
std::unique_ptr<std::byte[]> contiguous_features_;
48+
};
49+
50+
51+
/*****************************************************
52+
* I/O functions for fvecs and ivecs
53+
* Reference
54+
* https://github.com/facebookresearch/faiss/blob/e86bf8cae1a0ecdaee1503121421ed262ecee98c/demos/demo_sift1M.cpp
55+
*****************************************************/
56+
57+
auto fvecs_read(const char* fname, size_t& d_out, size_t& n_out)
58+
{
59+
std::error_code ec{};
60+
auto file_size = std::filesystem::file_size(fname, ec);
61+
if (ec != std::error_code{})
62+
{
63+
std::fprintf(stderr, "error when accessing file %s, size is: %ju message: %s \n", fname, file_size, ec.message().c_str());
64+
perror("");
65+
abort();
66+
}
67+
68+
// open as binary
69+
auto ifstream = std::ifstream(fname, std::ios::binary);
70+
if (!ifstream.is_open())
71+
{
72+
std::fprintf(stderr, "could not open %s\n", fname);
73+
perror("");
74+
abort();
75+
}
76+
77+
// read dimension header
78+
uint32_t dims = 0;
79+
ifstream.read(reinterpret_cast<char*>(&dims), sizeof(dims));
80+
assert((dims > 0 && dims < 1'000'000) && "unreasonable dimension");
81+
82+
// compute number of rows
83+
assert(file_size % ((dims + 1) * sizeof(float)) == 0 || !"weird file size");
84+
size_t n = (size_t)file_size / ((dims + 1) * sizeof(float));
85+
d_out = dims;
86+
n_out = n;
87+
88+
// read data rows (each row starts with its dimension, which is 4 bytes)
89+
auto x = std::make_unique<std::byte[]>(file_size);
90+
ifstream.seekg(0);
91+
ifstream.read(reinterpret_cast<char*>(x.get()), file_size);
92+
if (!ifstream) assert(ifstream.gcount() == static_cast<int>(file_size) || !"could not read whole file");
93+
94+
// shift array to remove row headers
95+
for (size_t i = 0; i < n; i++) std::memmove(&x[i * dims * sizeof(float)], &x[sizeof(dims) + i * (dims + 1) * sizeof(float)], dims * sizeof(float));
96+
97+
ifstream.close();
98+
return x;
99+
}
100+
101+
auto u8vecs_read(const char* fname, size_t& d_out, size_t& n_out)
102+
{
103+
// get total file size
104+
std::error_code ec{};
105+
auto file_size = std::filesystem::file_size(fname, ec);
106+
if (ec != std::error_code{})
107+
{
108+
std::fprintf(stderr, "error when accessing file %s, size is: %ju message: %s \n", fname, file_size, ec.message().c_str());
109+
std::abort();
110+
}
111+
112+
// open as binary
113+
auto ifstream = std::ifstream(fname, std::ios::binary);
114+
if (!ifstream.is_open())
115+
{
116+
std::fprintf(stderr, "could not open %s\n", fname);
117+
std::abort();
118+
}
119+
120+
// read dimension header
121+
uint32_t dims = 0;
122+
ifstream.read(reinterpret_cast<char*>(&dims), sizeof(dims));
123+
assert((dims > 0 && dims < 1'000'000) && "unreasonable dimension");
124+
125+
// compute number of rows
126+
assert(file_size % (dims + 4) == 0 || !"weird file size");
127+
size_t n = (size_t)file_size / (dims + 4);
128+
d_out = dims;
129+
n_out = n;
130+
131+
// read data rows (each row starts with its dimension, which is 4 bytes)
132+
auto x = std::make_unique<std::byte[]>(file_size);
133+
ifstream.seekg(0);
134+
ifstream.read(reinterpret_cast<char*>(x.get()), file_size);
135+
if (!ifstream) assert(ifstream.gcount() == static_cast<int>(file_size) || !"could not read whole file");
136+
137+
// shift array to remove row headers
138+
for (size_t i = 0; i < n; i++) std::memmove(&x[i * dims], &x[sizeof(dims) + i * (dims + sizeof(dims))], dims);
139+
140+
ifstream.close();
141+
return x;
142+
}
143+
144+
bool string_ends_with(const char* str, const char* suffix) {
145+
size_t str_len = std::strlen(str);
146+
size_t suffix_len = std::strlen(suffix);
147+
148+
if (suffix_len > str_len) {
149+
return false;
150+
}
151+
return std::strcmp(str + str_len - suffix_len, suffix) == 0;
152+
}
153+
154+
StaticFeatureRepository load_static_repository(const char* path_repository)
155+
{
156+
if (string_ends_with(path_repository, "fvecs")) {
157+
size_t dims;
158+
size_t count;
159+
auto contiguous_features = fvecs_read(path_repository, dims, count);
160+
return StaticFeatureRepository(std::move(contiguous_features), dims, count, sizeof(float));
161+
} else if (string_ends_with(path_repository, "u8vecs")) {
162+
size_t dims;
163+
size_t count;
164+
auto contiguous_features = u8vecs_read(path_repository, dims, count);
165+
return StaticFeatureRepository(std::move(contiguous_features), dims, count, sizeof(uint8_t));
166+
}
167+
168+
std::fprintf(stderr, "unsupported file extension, only fvecs and u8vecs are supported, but got %s \n", path_repository);
169+
std::perror("");
170+
std::abort();
171+
}
172+
173+
} // namespace deglib

‎cpp/benchmark/src/deglib_anns_bench.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <chrono>
77

88
#include "benchmark.h"
9+
#include "repository.h"
910
#include <deglib/deglib.h>
1011

1112

‎cpp/benchmark/src/deglib_build_bench.cpp‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <fmt/core.h>
99

1010
#include "benchmark.h"
11+
#include "repository.h"
1112
#include <deglib/deglib.h>
1213

1314
/**
@@ -563,7 +564,7 @@ static std::vector<float> estimate_recall(const deglib::graph::InternalGraph& gr
563564
size_t local_correct = 0;
564565
while (result_queue.empty() == false)
565566
{
566-
const auto internal_index = result_queue.top().getInternalIndex();
567+
const auto internal_index = result_queue.top().getIdentifier();
567568
const auto external_id = graph.getExternalLabel(internal_index);
568569
if (gt.find(external_id) != gt.end()) local_correct++;
569570
result_queue.pop();

‎cpp/benchmark/src/deglib_explore_bench.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <fmt/core.h>
44

55
#include "benchmark.h"
6+
#include "repository.h"
67
#include <deglib/deglib.h>
78

89
int main(int argc, char *argv[]) {

‎cpp/benchmark/src/deglib_groundtruth.cpp‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <omp.h>
77

88
#include "benchmark.h"
9+
#include "repository.h"
910
#include <deglib/deglib.h>
1011

1112
/**
@@ -106,7 +107,7 @@ std::vector<uint32_t> compute_knn_groundtruth(const deglib::FeatureRepository& b
106107

107108
auto topList = topLists.data() + (k_target*q);
108109
for(int32_t i = k_target - 1; i >= 0; i--) {
109-
topList[i] = results.top().getInternalIndex();
110+
topList[i] = results.top().getIdentifier();
110111
results.pop();
111112
}
112113

0 commit comments

Comments
 (0)