usearch 0.19.2 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +1 -1
- package/README.md +1 -1
- package/c/lib.cpp +1 -2
- package/c/test.c +238 -126
- package/conanfile.py +1 -1
- package/cpp/bench.cpp +3 -3
- package/cpp/test.cpp +12 -12
- package/include/usearch/index.hpp +137 -49
- package/include/usearch/index_punned_dense.hpp +1 -1
- package/include/usearch/index_punned_helpers.hpp +2 -0
- package/java/cloud/unum/usearch/cloud_unum_usearch_Index.cpp +25 -23
- package/javascript/lib.cpp +10 -11
- package/javascript/test.js +1 -1
- package/objc/USearchObjective.mm +15 -12
- package/objc/include/USearchObjective.h +3 -3
- package/package.json +2 -2
- package/python/lib.cpp +43 -48
- package/python/usearch/index.py +1 -1
- package/rust/lib.cpp +13 -13
- package/rust/lib.hpp +10 -6
- package/rust/lib.rs +2 -2
- package/swift/Index+Sugar.swift +13 -9
- package/wolfram/lib.cpp +26 -19
package/Cargo.toml
CHANGED
package/README.md
CHANGED
|
@@ -167,7 +167,7 @@ index.add(/* label: */ 42, /* vector: */ {&vec[0], 3});
|
|
|
167
167
|
auto results = index.search(/* query: */ {&vec[0], 3}, 5 /* neighbors */);
|
|
168
168
|
|
|
169
169
|
for (std::size_t i = 0; i != results.size(); ++i)
|
|
170
|
-
results[i].
|
|
170
|
+
results[i].member.label, results[i].member.vector, results[i].member.id, results[i].distance;
|
|
171
171
|
```
|
|
172
172
|
|
|
173
173
|
The `add` is thread-safe for concurrent index construction.
|
package/c/lib.cpp
CHANGED
|
@@ -15,8 +15,7 @@ using index_t = index_punned_dense_gt<label_t>;
|
|
|
15
15
|
using add_result_t = index_t::add_result_t;
|
|
16
16
|
using search_result_t = index_t::search_result_t;
|
|
17
17
|
using serialization_result_t = index_t::serialization_result_t;
|
|
18
|
-
|
|
19
|
-
using span_t = span_gt<float>;
|
|
18
|
+
using vector_view_t = span_gt<float>;
|
|
20
19
|
|
|
21
20
|
// helper functions that are not part of the C ABI
|
|
22
21
|
metric_kind_t to_native_metric(usearch_metric_kind_t kind) {
|
package/c/test.c
CHANGED
|
@@ -1,182 +1,294 @@
|
|
|
1
|
-
#include <
|
|
1
|
+
#include <stdio.h>
|
|
2
2
|
#include <errno.h>
|
|
3
3
|
#include <stdio.h>
|
|
4
4
|
#include <stdlib.h>
|
|
5
|
-
#include <string.h>
|
|
6
5
|
#include <sys/stat.h>
|
|
7
|
-
#include <time.h>
|
|
8
6
|
|
|
9
7
|
#include "usearch.h"
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
float skip;
|
|
16
|
-
|
|
17
|
-
;
|
|
18
|
-
if (stat(filename, &st) == -1) {
|
|
19
|
-
printf("Failed to read file: %s err: %d: %s\n", filename, errno, strerror(errno));
|
|
20
|
-
return NULL;
|
|
9
|
+
#define ASSERT(must_be_true, message) \
|
|
10
|
+
if (!(must_be_true)) { \
|
|
11
|
+
printf("Assert: %s\n", message); \
|
|
12
|
+
exit(-1); \
|
|
21
13
|
}
|
|
22
14
|
|
|
23
|
-
file = fopen(filename, "rb");
|
|
24
|
-
if (file == NULL) {
|
|
25
|
-
printf("Failed to open file: %s\n", filename);
|
|
26
|
-
return NULL;
|
|
27
|
-
}
|
|
28
15
|
|
|
29
|
-
|
|
30
|
-
cnt = fread(vector_dim, sizeof(int), 1, file);
|
|
31
|
-
assert(cnt == 1);
|
|
32
|
-
if (st.st_size % ((*vector_dim + 1) * sizeof(float)) != 0) {
|
|
33
|
-
printf("File does not contain a whole number of vectors.\n Vector dim: %ld, file size: %ld\n", *vector_dim,
|
|
34
|
-
st.st_size);
|
|
35
|
-
fclose(file);
|
|
36
|
-
return NULL;
|
|
37
|
-
}
|
|
16
|
+
void parse_vectors_from_file(char const* file_path, size_t* count, size_t* dimension, float** data) {
|
|
38
17
|
|
|
39
|
-
|
|
18
|
+
// Open the file
|
|
19
|
+
struct stat st = {};
|
|
20
|
+
ASSERT(stat(file_path, &st) == 0, "Failed to get metadata of the file");
|
|
21
|
+
FILE* file = fopen(file_path, "rb");
|
|
22
|
+
ASSERT(file, "Failed to open the file");
|
|
40
23
|
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
24
|
+
// Read vectors dimension and calculate count
|
|
25
|
+
int dim = 0;
|
|
26
|
+
size_t read = fread(&dim, sizeof(int), 1, file);
|
|
27
|
+
ASSERT(read == 1, "Failed to read from the file");
|
|
28
|
+
ASSERT(st.st_size % ((dim + 1) * sizeof(float)) == 0, "File does not contain a whole number of vectors");
|
|
29
|
+
*dimension = (size_t)dim;
|
|
30
|
+
*count = st.st_size / ((dim + 1) * sizeof(float));
|
|
48
31
|
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
32
|
+
// Allocate memory for the vectors' data
|
|
33
|
+
*data = (float*)malloc(*count * *dimension * sizeof(float));
|
|
34
|
+
ASSERT(*data, "Failed to allocate memory");
|
|
35
|
+
|
|
36
|
+
// Read the data
|
|
37
|
+
for (size_t i = 0; i < *count; ++i) {
|
|
38
|
+
read = fread(*data + i * *dimension, sizeof(float), *dimension, file);
|
|
39
|
+
ASSERT(read == *dimension, "Failed to read from the file");
|
|
40
|
+
if (i == *count - 1)
|
|
54
41
|
break;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
42
|
+
|
|
43
|
+
// Skip
|
|
44
|
+
float skip;
|
|
45
|
+
read = fread(&skip, sizeof(float), 1, file);
|
|
46
|
+
ASSERT(read == 1, "Failed to read from the file");
|
|
58
47
|
}
|
|
59
48
|
|
|
60
49
|
fclose(file);
|
|
61
|
-
return data;
|
|
62
50
|
}
|
|
63
51
|
|
|
64
|
-
|
|
65
|
-
const int LOG_GRANULARITY = 10000;
|
|
66
|
-
|
|
67
|
-
void test_index(float* data, size_t num_vectors, size_t vector_dim) {
|
|
52
|
+
usearch_init_options_t create_options(size_t vector_dimension) {
|
|
68
53
|
usearch_init_options_t opts;
|
|
69
|
-
usearch_index_t idx;
|
|
70
|
-
usearch_error_t error = NULL;
|
|
71
|
-
clock_t start;
|
|
72
54
|
opts.connectivity = 2; // 32 in faiss
|
|
73
|
-
opts.dimensions =
|
|
55
|
+
opts.dimensions = vector_dimension;
|
|
74
56
|
opts.expansion_add = 40; // 40 in faiss
|
|
75
57
|
opts.expansion_search = 16; // 10 in faiss
|
|
76
58
|
opts.metric_kind = usearch_metric_ip_k;
|
|
77
59
|
opts.metric = NULL;
|
|
78
60
|
opts.quantization = usearch_scalar_f32_k;
|
|
61
|
+
return opts;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
void test_init(size_t vectors_count, size_t vector_dimension) {
|
|
65
|
+
printf("Test: Index Initialization...\n");
|
|
66
|
+
|
|
67
|
+
// Init index
|
|
68
|
+
usearch_index_t idx = NULL;
|
|
69
|
+
usearch_error_t error = NULL;
|
|
70
|
+
usearch_init_options_t opts = create_options(vector_dimension);
|
|
71
|
+
idx = usearch_init(&opts, &error);
|
|
72
|
+
ASSERT(!error, error);
|
|
73
|
+
usearch_free(idx, &error);
|
|
74
|
+
ASSERT(!error, error);
|
|
75
|
+
|
|
76
|
+
// Init second time
|
|
77
|
+
idx = usearch_init(&opts, &error);
|
|
78
|
+
ASSERT(!error, error);
|
|
79
|
+
|
|
80
|
+
ASSERT(usearch_size(idx, &error) == 0, error);
|
|
81
|
+
ASSERT(usearch_capacity(idx, &error) == 0, error);
|
|
82
|
+
ASSERT(usearch_dimensions(idx, &error) == vector_dimension, error);
|
|
83
|
+
ASSERT(usearch_connectivity(idx, &error) == opts.connectivity, error);
|
|
84
|
+
|
|
85
|
+
// Reserve
|
|
86
|
+
usearch_reserve(idx, vectors_count, &error);
|
|
87
|
+
ASSERT(!error, error);
|
|
88
|
+
ASSERT(usearch_size(idx, &error) == 0, error);
|
|
89
|
+
ASSERT(usearch_capacity(idx, &error) == vectors_count, error);
|
|
90
|
+
ASSERT(usearch_dimensions(idx, &error) == vector_dimension, error);
|
|
91
|
+
ASSERT(usearch_connectivity(idx, &error) == opts.connectivity, error);
|
|
92
|
+
|
|
93
|
+
usearch_free(idx, &error);
|
|
94
|
+
ASSERT(!error, error);
|
|
95
|
+
|
|
96
|
+
printf("Test: Index Initialization - PASSED\n");
|
|
97
|
+
}
|
|
79
98
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
num_vectors /= 10;
|
|
83
|
-
usearch_label_t* labels = (usearch_label_t*)calloc(k, sizeof(usearch_label_t));
|
|
84
|
-
float* distances = (float*)calloc(k, sizeof(float));
|
|
99
|
+
void test_add_vector(size_t vectors_count, size_t vector_dimension, float const* data) {
|
|
100
|
+
printf("Test: Add Vector...\n");
|
|
85
101
|
|
|
86
|
-
|
|
87
|
-
|
|
102
|
+
usearch_index_t idx = NULL;
|
|
103
|
+
usearch_error_t error = NULL;
|
|
104
|
+
usearch_init_options_t opts = create_options(vector_dimension);
|
|
88
105
|
idx = usearch_init(&opts, &error);
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
106
|
+
usearch_reserve(idx, vectors_count, &error);
|
|
107
|
+
|
|
108
|
+
// Add vectors
|
|
109
|
+
for (size_t i = 0; i < vectors_count; ++i) {
|
|
110
|
+
usearch_label_t label = i;
|
|
111
|
+
usearch_add(idx, label, data + i * vector_dimension, usearch_scalar_f32_k, &error);
|
|
112
|
+
ASSERT(!error, error);
|
|
92
113
|
}
|
|
93
114
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
assert(!error);
|
|
115
|
+
ASSERT(usearch_size(idx, &error) == vectors_count, error);
|
|
116
|
+
ASSERT(usearch_capacity(idx, &error) == vectors_count, error);
|
|
97
117
|
|
|
98
|
-
|
|
99
|
-
for (size_t i = 0; i <
|
|
100
|
-
if (i % LOG_GRANULARITY == 0) {
|
|
101
|
-
fprintf(stderr, "added %ld vectors...\n", i);
|
|
102
|
-
}
|
|
118
|
+
// Check vectors in the index
|
|
119
|
+
for (size_t i = 0; i < vectors_count; ++i) {
|
|
103
120
|
usearch_label_t label = i;
|
|
104
|
-
|
|
105
|
-
assert(!error);
|
|
121
|
+
ASSERT(usearch_contains(idx, label, &error), error);
|
|
106
122
|
}
|
|
123
|
+
ASSERT(!usearch_contains(idx, -1, &error), error); // Non existing label
|
|
124
|
+
|
|
125
|
+
usearch_free(idx, &error);
|
|
126
|
+
printf("Test: Add Vector - PASSED\n");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
void test_find_vector(size_t vectors_count, size_t vector_dimension, float const* data) {
|
|
130
|
+
printf("Test: Find Vector...\n");
|
|
107
131
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
132
|
+
usearch_index_t idx = NULL;
|
|
133
|
+
usearch_error_t error = NULL;
|
|
134
|
+
usearch_init_options_t opts = create_options(vector_dimension);
|
|
135
|
+
idx = usearch_init(&opts, &error);
|
|
136
|
+
usearch_reserve(idx, vectors_count, &error);
|
|
137
|
+
|
|
138
|
+
// Create result buffers
|
|
139
|
+
int results_count = 10;
|
|
140
|
+
usearch_label_t* labels = (usearch_label_t*)malloc(results_count * sizeof(usearch_label_t));
|
|
141
|
+
float* distances = (float*)malloc(results_count * sizeof(float));
|
|
142
|
+
ASSERT(labels && distances, "Failed to allocate memory");
|
|
143
|
+
|
|
144
|
+
// Add vectors
|
|
145
|
+
for (size_t i = 0; i < vectors_count; ++i) {
|
|
113
146
|
usearch_label_t label = i;
|
|
114
|
-
|
|
115
|
-
|
|
147
|
+
usearch_add(idx, label, data + i * vector_dimension, usearch_scalar_f32_k, &error);
|
|
148
|
+
ASSERT(!error, error);
|
|
116
149
|
}
|
|
117
150
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
fprintf(stderr, "searched %ld vectors...\n", i);
|
|
125
|
-
}
|
|
126
|
-
const void *query_vector = data + i * vector_dim;
|
|
127
|
-
usearch_search(idx, query_vector, usearch_scalar_f32_k, k, labels, distances, &error);
|
|
128
|
-
assert(!error);
|
|
151
|
+
// Find the vectors
|
|
152
|
+
for (size_t i = 0; i < vectors_count; i++) {
|
|
153
|
+
const void *query_vector = data + i * vector_dimension;
|
|
154
|
+
size_t found_count = usearch_search(idx, query_vector, usearch_scalar_f32_k, results_count, labels, distances, &error);
|
|
155
|
+
ASSERT(!error, error);
|
|
156
|
+
ASSERT(found_count = results_count, "Vector is missing");
|
|
129
157
|
}
|
|
130
158
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
159
|
+
usearch_free(idx, &error);
|
|
160
|
+
printf("Test: Find Vector - PASSED\n");
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
void test_remove_vector(size_t vectors_count, size_t vector_dimension, float const* data) {
|
|
164
|
+
printf("Test: Remove Vector...\n");
|
|
165
|
+
|
|
166
|
+
usearch_index_t idx = NULL;
|
|
167
|
+
usearch_error_t error = NULL;
|
|
168
|
+
usearch_init_options_t opts = create_options(vector_dimension);
|
|
169
|
+
idx = usearch_init(&opts, &error);
|
|
170
|
+
usearch_reserve(idx, vectors_count, &error);
|
|
171
|
+
|
|
172
|
+
// Add vectors
|
|
173
|
+
for (size_t i = 0; i < vectors_count; ++i) {
|
|
174
|
+
usearch_label_t label = i;
|
|
175
|
+
usearch_add(idx, label, data + i * vector_dimension, usearch_scalar_f32_k, &error);
|
|
176
|
+
ASSERT(!error, error);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Remove the vectors
|
|
180
|
+
for (size_t i = 0; i < vectors_count; i++) {
|
|
181
|
+
usearch_label_t label = i;
|
|
182
|
+
usearch_remove(idx, label, &error);
|
|
183
|
+
ASSERT(error, "Currently, Remove is not supported");
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
usearch_free(idx, &error);
|
|
187
|
+
printf("Test: Remove Vector - PASSED\n");
|
|
188
|
+
}
|
|
136
189
|
|
|
137
|
-
|
|
138
|
-
|
|
190
|
+
void test_save_load(size_t vectors_count, size_t vector_dimension, float const* data) {
|
|
191
|
+
printf("Test: Save/Load...\n");
|
|
192
|
+
|
|
193
|
+
usearch_index_t idx = NULL;
|
|
194
|
+
usearch_error_t error = NULL;
|
|
195
|
+
usearch_init_options_t opts = create_options(vector_dimension);
|
|
196
|
+
idx = usearch_init(&opts, &error);
|
|
197
|
+
usearch_reserve(idx, vectors_count, &error);
|
|
198
|
+
|
|
199
|
+
// Add vectors
|
|
200
|
+
for (size_t i = 0; i < vectors_count; ++i) {
|
|
201
|
+
usearch_label_t label = i;
|
|
202
|
+
usearch_add(idx, label, data + i * vector_dimension, usearch_scalar_f32_k, &error);
|
|
203
|
+
ASSERT(!error, error);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Save and free the index
|
|
207
|
+
usearch_save(idx, "usearch_index.bin", &error);
|
|
208
|
+
ASSERT(!error, error);
|
|
139
209
|
usearch_free(idx, &error);
|
|
140
|
-
|
|
141
|
-
fprintf(stderr, "destroying the index took %.2f ms\n", ((double)(clock() - start)) / CLOCKS_PER_SEC * 1000);
|
|
210
|
+
ASSERT(!error, error);
|
|
142
211
|
|
|
143
|
-
|
|
144
|
-
start = clock();
|
|
212
|
+
// Reinit
|
|
145
213
|
idx = usearch_init(&opts, &error);
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
214
|
+
ASSERT(!error, error);
|
|
215
|
+
ASSERT(usearch_size(idx, &error) == 0, error);
|
|
216
|
+
|
|
217
|
+
// Load
|
|
149
218
|
usearch_load(idx, "usearch_index.bin", &error);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
219
|
+
ASSERT(!error, error);
|
|
220
|
+
ASSERT(usearch_size(idx, &error) == vectors_count, error);
|
|
221
|
+
ASSERT(usearch_capacity(idx, &error) == vectors_count, error);
|
|
222
|
+
ASSERT(usearch_dimensions(idx, &error) == vector_dimension, error);
|
|
223
|
+
ASSERT(usearch_connectivity(idx, &error) == opts.connectivity, error);
|
|
224
|
+
|
|
225
|
+
// Check vectors in the index
|
|
226
|
+
for (size_t i = 0; i < vectors_count; ++i) {
|
|
227
|
+
usearch_label_t label = i;
|
|
228
|
+
ASSERT(usearch_contains(idx, label, &error), error);
|
|
229
|
+
}
|
|
230
|
+
|
|
154
231
|
usearch_free(idx, &error);
|
|
232
|
+
printf("Test: Save/Load - PASSED\n");
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
void test_view(size_t vectors_count, size_t vector_dimension, float const* data) {
|
|
236
|
+
printf("Test: View...\n");
|
|
155
237
|
|
|
156
|
-
|
|
157
|
-
|
|
238
|
+
usearch_index_t idx = NULL;
|
|
239
|
+
usearch_error_t error = NULL;
|
|
240
|
+
usearch_init_options_t opts = create_options(vector_dimension);
|
|
158
241
|
idx = usearch_init(&opts, &error);
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
242
|
+
usearch_reserve(idx, vectors_count, &error);
|
|
243
|
+
|
|
244
|
+
// Add vectors
|
|
245
|
+
for (size_t i = 0; i < vectors_count; ++i) {
|
|
246
|
+
usearch_label_t label = i;
|
|
247
|
+
usearch_add(idx, label, data + i * vector_dimension, usearch_scalar_f32_k, &error);
|
|
248
|
+
ASSERT(!error, error);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Save and free the index
|
|
252
|
+
usearch_save(idx, "usearch_index.bin", &error);
|
|
253
|
+
ASSERT(!error, error);
|
|
167
254
|
usearch_free(idx, &error);
|
|
255
|
+
ASSERT(!error, error);
|
|
256
|
+
|
|
257
|
+
// Reinit
|
|
258
|
+
idx = usearch_init(&opts, &error);
|
|
259
|
+
ASSERT(!error, error);
|
|
260
|
+
|
|
261
|
+
// View
|
|
262
|
+
usearch_view(idx, "usearch_index.bin", &error);
|
|
263
|
+
ASSERT(!error, error);
|
|
168
264
|
|
|
265
|
+
usearch_free(idx, &error);
|
|
266
|
+
printf("Test: View - PASSED\n");
|
|
169
267
|
}
|
|
170
268
|
|
|
171
|
-
int main() {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
269
|
+
int main(int argc, char* argv[]) {
|
|
270
|
+
// Resolve file path
|
|
271
|
+
char const* filename = "sample.fvecs";
|
|
272
|
+
if (argc == 2)
|
|
273
|
+
filename = argv[1];
|
|
176
274
|
|
|
177
|
-
|
|
275
|
+
// Read data from the file
|
|
276
|
+
float* data = NULL;
|
|
277
|
+
size_t vectors_count = 0;
|
|
278
|
+
size_t vector_dimension = 0;
|
|
279
|
+
parse_vectors_from_file(filename, &vectors_count, &vector_dimension, &data);
|
|
280
|
+
vectors_count = vectors_count > 100000 ? 100000 : vectors_count; // Just limit vectors
|
|
281
|
+
|
|
282
|
+
// Test
|
|
283
|
+
test_init(vectors_count, vector_dimension);
|
|
284
|
+
test_add_vector(vectors_count, vector_dimension, data);
|
|
285
|
+
test_find_vector(vectors_count, vector_dimension, data);
|
|
286
|
+
test_remove_vector(vectors_count, vector_dimension, data);
|
|
287
|
+
test_save_load(vectors_count, vector_dimension, data);
|
|
288
|
+
test_view(vectors_count, vector_dimension, data);
|
|
289
|
+
|
|
290
|
+
// Free vectors' buffer
|
|
291
|
+
free(data);
|
|
178
292
|
|
|
179
|
-
free(data); // Remember to free the dynamically allocated memory
|
|
180
|
-
}
|
|
181
293
|
return 0;
|
|
182
294
|
}
|
package/conanfile.py
CHANGED
|
@@ -4,7 +4,7 @@ from conans import ConanFile
|
|
|
4
4
|
class USearchConan(ConanFile):
|
|
5
5
|
|
|
6
6
|
name = 'USearch'
|
|
7
|
-
version = '0.
|
|
7
|
+
version = '0.20.0'
|
|
8
8
|
license = 'Apache 2.0'
|
|
9
9
|
url = 'https://github.com/unum-cloud/usearch'
|
|
10
10
|
description = 'Smaller & Faster Single-File Vector Search Engine from Unum'
|
package/cpp/bench.cpp
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* @brief A benchmark for the construction speed of the USearch index
|
|
3
|
+
* and the resulting accuracy (recall) of the Approximate Nearest Neighbors
|
|
4
|
+
* Search queries.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
|
package/cpp/test.cpp
CHANGED
|
@@ -9,8 +9,6 @@
|
|
|
9
9
|
using namespace unum::usearch;
|
|
10
10
|
using namespace unum;
|
|
11
11
|
|
|
12
|
-
using point_id_t = std::int64_t;
|
|
13
|
-
|
|
14
12
|
void expect(bool must_be_true) {
|
|
15
13
|
if (!must_be_true)
|
|
16
14
|
throw std::runtime_error("Failed!");
|
|
@@ -22,6 +20,7 @@ template <typename scalar_at, typename index_at> void test3d(index_at&& index) {
|
|
|
22
20
|
using view_t = span_gt<scalar_t const>;
|
|
23
21
|
using index_t = typename std::remove_reference<index_at>::type;
|
|
24
22
|
using distance_t = typename index_t::distance_t;
|
|
23
|
+
using label_t = typename index_t::label_t;
|
|
25
24
|
|
|
26
25
|
scalar_t vec[3] = {10, 20, 15};
|
|
27
26
|
scalar_t vec_a[3] = {15, 16, 17};
|
|
@@ -31,7 +30,7 @@ template <typename scalar_at, typename index_at> void test3d(index_at&& index) {
|
|
|
31
30
|
index.add(42, view_t{&vec[0], 3ul});
|
|
32
31
|
|
|
33
32
|
// Default approximate search
|
|
34
|
-
|
|
33
|
+
label_t matched_labels[10] = {0};
|
|
35
34
|
distance_t matched_distances[10] = {0};
|
|
36
35
|
std::size_t matched_count = index.search(view_t{&vec[0], 3ul}, 5).dump_to(matched_labels, matched_distances);
|
|
37
36
|
|
|
@@ -52,7 +51,7 @@ template <typename scalar_at, typename index_at> void test3d(index_at&& index) {
|
|
|
52
51
|
// Validate scans
|
|
53
52
|
std::size_t count = 0;
|
|
54
53
|
for (auto member : index) {
|
|
55
|
-
|
|
54
|
+
label_t id = member.label;
|
|
56
55
|
expect(id >= 42 && id <= 44);
|
|
57
56
|
count++;
|
|
58
57
|
}
|
|
@@ -146,11 +145,12 @@ int main(int, char**) {
|
|
|
146
145
|
// static_assert(!std::is_same<index_gt<pearson_correlation_gt<>>::value_type, std::true_type>());
|
|
147
146
|
// static_assert(!std::is_same<index_gt<haversine_gt<>>::value_type, std::true_type>());
|
|
148
147
|
|
|
149
|
-
|
|
150
|
-
test3d<float>(index_gt<
|
|
148
|
+
using big_point_id_t = std::int64_t;
|
|
149
|
+
test3d<float>(index_gt<cos_gt<float>, big_point_id_t, std::uint32_t>{});
|
|
150
|
+
test3d<float>(index_gt<l2sq_gt<float>, big_point_id_t, std::uint32_t>{});
|
|
151
151
|
|
|
152
|
-
test3d<double>(index_gt<cos_gt<double>,
|
|
153
|
-
test3d<double>(index_gt<l2sq_gt<double>,
|
|
152
|
+
test3d<double>(index_gt<cos_gt<double>, big_point_id_t, std::uint32_t>{});
|
|
153
|
+
test3d<double>(index_gt<l2sq_gt<double>, big_point_id_t, std::uint32_t>{});
|
|
154
154
|
|
|
155
155
|
test3d<float>(punned_small_t::make(3, metric_kind_t::cos_k));
|
|
156
156
|
test3d<float>(punned_small_t::make(3, metric_kind_t::l2sq_k));
|
|
@@ -161,11 +161,11 @@ int main(int, char**) {
|
|
|
161
161
|
test3d_punned<float>(punned_small_t::make(3, metric_kind_t::cos_k));
|
|
162
162
|
test3d_punned<float>(punned_small_t::make(3, metric_kind_t::l2sq_k));
|
|
163
163
|
|
|
164
|
-
test_sets(index_gt<jaccard_gt<std::int32_t, float>,
|
|
165
|
-
test_sets(index_gt<jaccard_gt<std::int64_t, float>,
|
|
164
|
+
test_sets(index_gt<jaccard_gt<std::int32_t, float>, big_point_id_t, std::uint32_t>{});
|
|
165
|
+
test_sets(index_gt<jaccard_gt<std::int64_t, float>, big_point_id_t, std::uint32_t>{});
|
|
166
166
|
|
|
167
|
-
test_sets_moved<index_gt<jaccard_gt<std::int32_t, float>,
|
|
168
|
-
test_sets_moved<index_gt<jaccard_gt<std::int64_t, float>,
|
|
167
|
+
test_sets_moved<index_gt<jaccard_gt<std::int32_t, float>, big_point_id_t, std::uint32_t>>();
|
|
168
|
+
test_sets_moved<index_gt<jaccard_gt<std::int64_t, float>, big_point_id_t, std::uint32_t>>();
|
|
169
169
|
|
|
170
170
|
return 0;
|
|
171
171
|
}
|