Skip to content

Commit e41bc6b

Browse files
committed
Reverting some more auto declarations and adding ctest support
1 parent 733751d commit e41bc6b

File tree

10 files changed

+55
-24
lines changed

10 files changed

+55
-24
lines changed

CMakeLists.txt

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,25 @@ include(FetchContent)
99

1010
# These example/test targets catch exceptions, so exceptions should always be
1111
# enabled building these files even if they are disabled in other targets.
12+
# We check that each target included in this list is a real target.
1213
set(HNSWLIB_TARGETS_REQUIRING_EXCEPTIONS
1314
example_mt_filter
1415
example_mt_replace_deleted
1516
example_mt_search
1617
multiThread_replace_test
1718
test_updates)
1819

19-
20+
# Adds an example or test target. The target name parameter is followed by
21+
# the list of source files. Automatically links with the hnswlib library.
22+
# Also decides whether to enable exceptions when building the target.
23+
# If HNSWLIB_ENABLE_EXCEPTIONS is ON, exceptions are always enabled.
24+
# If HNSWLIB_ENABLE_EXCEPTIONS is OFF, exceptions are only enabled for the
25+
# specific targets listed in HNSWLIB_TARGETS_REQUIRING_EXCEPTIONS.
2026
function(add_example_or_test TARGET_NAME ...)
2127
add_executable(${ARGV})
22-
target_link_libraries("${TARGET_NAME}" ${common_link_libraries})
23-
list(FIND HNSWLIB_TARGETS_REQUIRING_EXCEPTIONS "${TARGET_NAME}" _index)
24-
if(_index GREATER -1)
28+
target_link_libraries(${TARGET_NAME} hnswlib)
29+
list(FIND HNSWLIB_TARGETS_REQUIRING_EXCEPTIONS "${TARGET_NAME}" found_at_index)
30+
if(found_at_index GREATER -1)
2531
if(NOT HNSWLIB_ENABLE_EXCEPTIONS)
2632
message("Enabling exceptions for target ${TARGET_NAME} as a special case")
2733
endif()
@@ -34,9 +40,20 @@ function(add_example_or_test TARGET_NAME ...)
3440
else()
3541
target_compile_options("${TARGET_NAME}" PUBLIC -fno-exceptions)
3642
endif()
43+
if(NOT ${TARGET_NAME} STREQUAL "main")
44+
add_test(
45+
NAME ${TARGET_NAME}
46+
COMMAND ${TARGET_NAME}
47+
)
48+
endif()
3749
endfunction()
3850

3951
option(HNSWLIB_ENABLE_EXCEPTIONS "Whether to enable exceptions in hnswlib" ON)
52+
if(HNSWLIB_ENABLE_EXCEPTIONS)
53+
message("Exceptions are enabled using HNSWLIB_ENABLE_EXCEPTIONS=ON (default)")
54+
else()
55+
message("Exceptions are disabled using HNSWLIB_ENABLE_EXCEPTIONS=OFF")
56+
endif()
4057

4158
set(CMAKE_CXX_STANDARD 11)
4259

@@ -62,10 +79,12 @@ install(EXPORT hnswlibTargets
6279
# Examples and tests
6380
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
6481
option(HNSWLIB_EXAMPLES "Build examples and tests." ON)
82+
message("Building examples and tests")
6583
else()
6684
option(HNSWLIB_EXAMPLES "Build examples and tests." OFF)
6785
endif()
6886
if(HNSWLIB_EXAMPLES)
87+
enable_testing()
6988
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
7089
SET( CMAKE_CXX_FLAGS "-Ofast -DHAVE_CXX0X -openmp -fpic -ftree-vectorize" )
7190
check_cxx_compiler_flag("-march=native" COMPILER_SUPPORT_NATIVE_FLAG)
@@ -85,9 +104,6 @@ if(HNSWLIB_EXAMPLES)
85104
SET( CMAKE_CXX_FLAGS "/O2 -DHAVE_CXX0X /W1 /openmp /EHsc" )
86105
endif()
87106

88-
set(common_link_libraries
89-
hnswlib)
90-
91107
set(EXAMPLE_NAMES
92108
example_epsilon_search
93109
example_filter
@@ -103,7 +119,7 @@ if(HNSWLIB_EXAMPLES)
103119
endforeach()
104120

105121
set(TEST_NAMES
106-
multivector_search_test
122+
multivector_search_test
107123
epsilon_search_test
108124
searchKnnCloserFirst_test
109125
searchKnnWithFilter_test
@@ -116,5 +132,15 @@ if(HNSWLIB_EXAMPLES)
116132
# This test deviates from the above pattern of naming test executables.
117133
add_example_or_test(test_updates tests/cpp/updates_test.cpp)
118134

135+
# For historical reasons, the "main" program links with sift_1b.cpp.
119136
add_example_or_test(main tests/cpp/main.cpp tests/cpp/sift_1b.cpp)
137+
138+
foreach(target_name IN LISTS HNSWLIB_TARGETS_REQUIRING_EXCEPTIONS)
139+
if(NOT TARGET ${target_name})
140+
message(FATAL_ERROR
141+
"Target '${target_name}' included in "
142+
"HNSWLIB_TARGETS_REQUIRING_EXCEPTIONS does not exist. "
143+
"Please check if this is a typo.")
144+
endif()
145+
endforeach()
120146
endif()

examples/cpp/example_filter.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ int main() {
4545
// Query the elements for themselves with filter and check returned labels
4646
int k = 10;
4747
for (int i = 0; i < max_elements; i++) {
48-
std::vector<std::pair<float, hnswlib::labeltype>> result =
49-
alg_hnsw->searchKnnCloserFirst(data + i * dim, k, &pickIdsDivisibleByTwo);
48+
std::vector<std::pair<float, hnswlib::labeltype>> result = alg_hnsw->searchKnnCloserFirst(data + i * dim, k, &pickIdsDivisibleByTwo);
5049
for (auto item: result) {
5150
if (item.second % 2 == 1) std::cout << "Error: found odd label\n";
5251
}

examples/cpp/example_mt_filter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ int main() {
106106
int k = 10;
107107
std::vector<hnswlib::labeltype> neighbors(max_elements * k);
108108
ParallelFor(0, max_elements, num_threads, [&](size_t row, size_t threadId) {
109-
auto result = alg_hnsw->searchKnn(data + dim * row, k, &pickIdsDivisibleByTwo);
109+
std::priority_queue<std::pair<float, hnswlib::labeltype>> result = alg_hnsw->searchKnn(data + dim * row, k, &pickIdsDivisibleByTwo);
110110
for (int i = 0; i < k; i++) {
111111
hnswlib::labeltype label = result.top().second;
112112
result.pop();

examples/cpp/example_mt_search.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ int main() {
8989
// Query the elements for themselves and measure recall
9090
std::vector<hnswlib::labeltype> neighbors(max_elements);
9191
ParallelFor(0, max_elements, num_threads, [&](size_t row, size_t threadId) {
92-
auto result = alg_hnsw->searchKnn(data + dim * row, 1);
92+
std::priority_queue<std::pair<float, hnswlib::labeltype>> result = alg_hnsw->searchKnn(data + dim * row, 1);
9393
hnswlib::labeltype label = result.top().second;
9494
neighbors[row] = label;
9595
});

examples/cpp/example_search.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ int main() {
2929
// Query the elements for themselves and measure recall
3030
float correct = 0;
3131
for (int i = 0; i < max_elements; i++) {
32-
auto result = alg_hnsw->searchKnn(data + i * dim, 1);
32+
std::priority_queue<std::pair<float, hnswlib::labeltype>> result = alg_hnsw->searchKnn(data + i * dim, 1);
3333
hnswlib::labeltype label = result.top().second;
3434
if (label == i) correct++;
3535
}
@@ -45,7 +45,7 @@ int main() {
4545
alg_hnsw = new hnswlib::HierarchicalNSW<float>(&space, hnsw_path);
4646
correct = 0;
4747
for (int i = 0; i < max_elements; i++) {
48-
auto result = alg_hnsw->searchKnn(data + i * dim, 1);
48+
std::priority_queue<std::pair<float, hnswlib::labeltype>> result = alg_hnsw->searchKnn(data + i * dim, 1);
4949
hnswlib::labeltype label = result.top().second;
5050
if (label == i) correct++;
5151
}

hnswlib/bruteforce.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class BruteforceSearch : public AlgorithmInterface<dist_t> {
7474
idx = search->second;
7575
} else {
7676
if (cur_element_count >= maxelements_) {
77-
HNSWLIB_THROW_RUNTIME_ERROR("The number of elements exceeds the specified limit\n");
77+
HNSWLIB_THROW_RUNTIME_ERROR("The number of elements exceeds the specified limit");
7878
}
7979
idx = cur_element_count;
8080
dict_external_to_internal[label] = idx;

hnswlib/hnswalg.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,10 @@ class HierarchicalNSW : public AlgorithmInterface<dist_t> {
717717

718718

719719
void loadIndex(const std::string &location, SpaceInterface<dist_t> *s, size_t max_elements_i = 0) {
720+
Status status = loadIndexNoExceptions(location, s, max_elements_i);
721+
if (!status.ok()) {
722+
HNSWLIB_THROW_RUNTIME_ERROR(status.message());
723+
}
720724
}
721725

722726
Status loadIndexNoExceptions(const std::string &location, SpaceInterface<dist_t> *s, size_t max_elements_i = 0) {

hnswlib/hnswlib.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ static bool AVX512Capable() {
124124

125125
#if defined(__EXCEPTIONS)
126126
#define HNSWLIB_THROW_RUNTIME_ERROR(message) throw std::runtime_error(message)
127-
#else
127+
#else
128128
#define HNSWLIB_THROW_RUNTIME_ERROR(message) do { \
129129
fprintf(stderr, \
130130
"FATAL: hnswlib compiled without exception support. " \
@@ -142,7 +142,7 @@ class [[nodiscard]] Status {
142142
public:
143143
Status() : message_(nullptr) {}
144144

145-
// Constructor with an error message (can't be nullptr).
145+
// Constructor with an error message (nullptr is interpreted as OK status).
146146
Status(const char* message) : message_(message) {}
147147

148148
// Returns true if the status is OK

tests/cpp/multivector_search_test.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ int main() {
1414
int num_queries = 100;
1515
int num_docs = 10; // Number of documents to search
1616
int ef_collection = 15; // Number of candidate documents during the search
17-
// Controlls the recall: higher ef leads to better accuracy, but slower search
17+
// Controls the recall: higher ef leads to better accuracy, but slower search
1818
docidtype min_doc_id = 0;
1919
docidtype max_doc_id = 49;
2020

21-
// Initing index
21+
// Initializing index
2222
hnswlib::MultiVectorL2Space<docidtype> space(dim);
2323
hnswlib::BruteforceSearch<dist_t>* alg_brute = new hnswlib::BruteforceSearch<dist_t>(&space, max_elements);
2424
hnswlib::HierarchicalNSW<dist_t>* alg_hnsw = new hnswlib::HierarchicalNSW<dist_t>(&space, max_elements, M, ef_construction);
@@ -67,7 +67,7 @@ int main() {
6767
*(float*)vec_data = value;
6868
}
6969
hnswlib::MultiVectorSearchStopCondition<docidtype, dist_t> stop_condition(space, num_docs, ef_collection);
70-
auto hnsw_results =
70+
std::vector<std::pair<dist_t, hnswlib::labeltype>> hnsw_results =
7171
alg_hnsw->searchStopConditionClosest(query_data, stop_condition);
7272

7373
// check number of found documents
@@ -82,7 +82,7 @@ int main() {
8282
assert(hnsw_docs.size() == num_docs);
8383

8484
// Check overall recall
85-
auto gt_results =
85+
std::vector<std::pair<dist_t, hnswlib::labeltype>> gt_results =
8686
alg_brute->searchKnnCloserFirst(query_data, max_elements);
8787
std::unordered_set<docidtype> gt_docs;
8888
for (int i = 0; i < gt_results.size(); i++) {
@@ -100,14 +100,16 @@ int main() {
100100
delete[] query_data;
101101
}
102102
float recall = correct / total_num_elements;
103-
std::cout << "random elements search recall : " << recall << "\n";
103+
std::cout << "random elements search recall : " << recall << std::endl;
104+
std::cout << "correct=" << correct << std::endl;
105+
std::cout << "total_num_elements=" << total_num_elements << std::endl;
104106
assert(recall > 0.95);
105107

106108
// Query the elements for themselves and measure recall
107109
correct = 0;
108110
for (int i = 0; i < max_elements; i++) {
109111
hnswlib::MultiVectorSearchStopCondition<docidtype, dist_t> stop_condition(space, num_docs, ef_collection);
110-
auto result =
112+
std::vector<std::pair<float, hnswlib::labeltype>> result =
111113
alg_hnsw->searchStopConditionClosest(data + i * data_point_size, stop_condition);
112114
hnswlib::labeltype label = -1;
113115
if (!result.empty()) {

tests/cpp/sift_1b.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ test_approx(
179179
// uncomment to test in parallel mode:
180180
//#pragma omp parallel for
181181
for (int i = 0; i < qsize; i++) {
182-
auto result = appr_alg.searchKnn(massQ + vecdim * i, k);
182+
std::priority_queue<std::pair<int, labeltype >> result = appr_alg.searchKnn(massQ + vecdim * i, k);
183183
std::priority_queue<std::pair<int, labeltype >> gt(answers[i]);
184184
unordered_set<labeltype> g;
185185
total += gt.size();

0 commit comments

Comments
 (0)