usearch 0.2.2 → 0.2.4
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/.github/workflows/release.yml +39 -15
- package/.github/workflows/update_version.sh +6 -0
- package/.releaserc +77 -0
- package/.vscode/settings.json +10 -1
- package/Cargo.toml +1 -1
- package/README.md +281 -230
- package/VERSION +1 -1
- package/conanfile.py +3 -2
- package/docs/Benchmarking.md +182 -0
- package/docs/Compilation.md +112 -0
- package/include/usearch/usearch.hpp +212 -116
- package/objc/include/USearchObjective.h +10 -9
- package/package.json +7 -1
- package/python/bench.py +100 -28
- package/python/lib.cpp +51 -28
- package/python/test.py +78 -36
- package/setup.py +11 -3
- package/simsimd/include/simsimd/simsimd.h +31 -41
- package/src/advanced.hpp +58 -23
- package/src/bench.cpp +11 -15
- package/.github/workflows/package.json +0 -82
- package/CMakeListsInstructions.md +0 -185
package/src/advanced.hpp
CHANGED
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
#include <thread> // `std::thread`
|
|
15
15
|
#include <vector> // `std::vector`
|
|
16
16
|
|
|
17
|
+
#if defined(_OPENMP)
|
|
18
|
+
#include <omp.h> // `omp_get_num_threads()`
|
|
19
|
+
#endif
|
|
20
|
+
|
|
17
21
|
#if __linux__
|
|
18
22
|
#include <sys/auxv.h>
|
|
19
23
|
#endif
|
|
@@ -170,6 +174,29 @@ class f8_bits_t {
|
|
|
170
174
|
|
|
171
175
|
inline f16_bits_t::f16_bits_t(f8_bits_t v) noexcept : f16_bits_t(float(v)) {}
|
|
172
176
|
|
|
177
|
+
struct cos_f8_t {
|
|
178
|
+
punned_distance_t operator()(f8_bits_t const* a, f8_bits_t const* b, std::size_t n) const noexcept {
|
|
179
|
+
std::int32_t ab{}, a2{}, b2{};
|
|
180
|
+
for (std::size_t i = 0; i != n; i++) {
|
|
181
|
+
std::int16_t ai{a[i]};
|
|
182
|
+
std::int16_t bi{b[i]};
|
|
183
|
+
ab += ai * bi;
|
|
184
|
+
a2 += square(ai);
|
|
185
|
+
b2 += square(bi);
|
|
186
|
+
}
|
|
187
|
+
return 1.f - ab / (std::sqrt(a2) * std::sqrt(b2));
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
struct l2sq_f8_t {
|
|
192
|
+
punned_distance_t operator()(f8_bits_t const* a, f8_bits_t const* b, std::size_t n) const noexcept {
|
|
193
|
+
std::int32_t ab_deltas_sq{};
|
|
194
|
+
for (std::size_t i = 0; i != n; i++)
|
|
195
|
+
ab_deltas_sq += square(std::int16_t(a[i]) - std::int16_t(b[i]));
|
|
196
|
+
return ab_deltas_sq;
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
|
|
173
200
|
struct uuid_t {
|
|
174
201
|
std::uint8_t octets[16];
|
|
175
202
|
};
|
|
@@ -179,12 +206,18 @@ void multithreaded(std::size_t threads, std::size_t tasks, callback_at&& callbac
|
|
|
179
206
|
|
|
180
207
|
if (threads == 0)
|
|
181
208
|
threads = std::thread::hardware_concurrency();
|
|
182
|
-
if (threads == 1) {
|
|
209
|
+
if (threads == 1 || tasks <= 128) {
|
|
183
210
|
for (std::size_t task_idx = 0; task_idx < tasks; ++task_idx)
|
|
184
211
|
callback(0, task_idx);
|
|
185
212
|
return;
|
|
186
213
|
}
|
|
187
214
|
|
|
215
|
+
#if defined(_OPENMP)
|
|
216
|
+
omp_set_num_threads(threads);
|
|
217
|
+
#pragma omp parallel for schedule(dynamic)
|
|
218
|
+
for (std::size_t i = 0; i < tasks; ++i)
|
|
219
|
+
callback(omp_get_thread_num(), i);
|
|
220
|
+
#else
|
|
188
221
|
std::vector<std::thread> threads_pool;
|
|
189
222
|
std::size_t tasks_per_thread = (tasks / threads) + ((tasks % threads) != 0);
|
|
190
223
|
for (std::size_t thread_idx = 0; thread_idx != threads; ++thread_idx) {
|
|
@@ -194,9 +227,9 @@ void multithreaded(std::size_t threads, std::size_t tasks, callback_at&& callbac
|
|
|
194
227
|
callback(thread_idx, task_idx);
|
|
195
228
|
});
|
|
196
229
|
}
|
|
197
|
-
|
|
198
230
|
for (std::size_t thread_idx = 0; thread_idx != threads; ++thread_idx)
|
|
199
231
|
threads_pool[thread_idx].join();
|
|
232
|
+
#endif
|
|
200
233
|
}
|
|
201
234
|
|
|
202
235
|
/**
|
|
@@ -424,6 +457,7 @@ class auto_index_gt {
|
|
|
424
457
|
config_t const& config() const noexcept { return root_config_; }
|
|
425
458
|
void clear() noexcept { return index_->clear(); }
|
|
426
459
|
|
|
460
|
+
accuracy_t accuracy() const noexcept { return accuracy_; }
|
|
427
461
|
isa_t acceleration() const noexcept { return acceleration_; }
|
|
428
462
|
std::size_t concurrency() const noexcept {
|
|
429
463
|
return (std::min)(root_config_.max_threads_add, root_config_.max_threads_search);
|
|
@@ -484,7 +518,11 @@ class auto_index_gt {
|
|
|
484
518
|
|
|
485
519
|
private:
|
|
486
520
|
static index_t* aligned_index_alloc() noexcept {
|
|
521
|
+
#if defined(WINDOWS)
|
|
522
|
+
return (index_t*)_aligned_malloc(64, 64 * divide_round_up<64>(sizeof(index_t)));
|
|
523
|
+
#else
|
|
487
524
|
return (index_t*)aligned_alloc(64, 64 * divide_round_up<64>(sizeof(index_t)));
|
|
525
|
+
#endif
|
|
488
526
|
}
|
|
489
527
|
|
|
490
528
|
static void aligned_index_free(index_t* raw) noexcept { free(raw); }
|
|
@@ -641,43 +679,40 @@ class auto_index_gt {
|
|
|
641
679
|
return {pun_metric<f32_t>(ip_gt<f32_t>{}), isa_t::auto_k};
|
|
642
680
|
}
|
|
643
681
|
|
|
644
|
-
static metric_and_meta_t
|
|
682
|
+
static metric_and_meta_t cos_metric_f16(std::size_t dimensions) {
|
|
645
683
|
(void)dimensions;
|
|
646
684
|
#if defined(USEARCH_USE_SIMD)
|
|
647
685
|
#if defined(__x86_64__)
|
|
648
|
-
if (dimensions %
|
|
686
|
+
if (dimensions % 16 == 0)
|
|
649
687
|
return {
|
|
650
688
|
pun_metric<simsimd_f16_t>([](simsimd_f16_t const* a, simsimd_f16_t const* b, size_t d) noexcept {
|
|
651
|
-
return 1.f -
|
|
689
|
+
return 1.f - simsimd_cos_f16x16avx512(a, b, d);
|
|
652
690
|
}),
|
|
653
691
|
isa_t::avx512_k,
|
|
654
692
|
};
|
|
655
693
|
#elif defined(__aarch64__)
|
|
656
|
-
if (
|
|
657
|
-
return {
|
|
658
|
-
pun_metric<simsimd_f16_t>([](simsimd_f16_t const* a, simsimd_f16_t const* b, size_t d) noexcept {
|
|
659
|
-
return 1.f - simsimd_dot_f16sve(a, b, d);
|
|
660
|
-
}),
|
|
661
|
-
isa_t::sve_k,
|
|
662
|
-
};
|
|
663
|
-
if (dimensions % 8 == 0)
|
|
694
|
+
if (dimensions % 4 == 0)
|
|
664
695
|
return {
|
|
665
696
|
pun_metric<simsimd_f16_t>([](simsimd_f16_t const* a, simsimd_f16_t const* b, size_t d) noexcept {
|
|
666
|
-
return 1.f -
|
|
697
|
+
return 1.f - simsimd_cos_f16x4neon(a, b, d);
|
|
667
698
|
}),
|
|
668
699
|
isa_t::neon_k,
|
|
669
700
|
};
|
|
670
701
|
#endif
|
|
671
702
|
#endif
|
|
672
|
-
return {pun_metric<f16_bits_t>(
|
|
703
|
+
return {pun_metric<f16_bits_t>(cos_gt<f16_bits_t, f32_t>{}), isa_t::auto_k};
|
|
673
704
|
}
|
|
674
705
|
|
|
675
706
|
static metric_and_meta_t ip_metric(std::size_t dimensions, accuracy_t accuracy) {
|
|
676
707
|
switch (accuracy) {
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
case accuracy_t::
|
|
708
|
+
case accuracy_t::f32_k:
|
|
709
|
+
// The two most common numeric types for the most common metric have optimized versions
|
|
710
|
+
return ip_metric_f32(dimensions);
|
|
711
|
+
case accuracy_t::f16_k:
|
|
712
|
+
// Dot-product accumulates error, Cosine-distance normalizes it
|
|
713
|
+
return cos_metric_f16(dimensions);
|
|
714
|
+
|
|
715
|
+
case accuracy_t::f8_k: return {pun_metric<f8_bits_t>(cos_f8_t{}), isa_t::auto_k};
|
|
681
716
|
case accuracy_t::f64_k: return {pun_metric<f64_t>(ip_gt<f64_t>{}), isa_t::auto_k};
|
|
682
717
|
default: return {};
|
|
683
718
|
}
|
|
@@ -685,7 +720,7 @@ class auto_index_gt {
|
|
|
685
720
|
|
|
686
721
|
static metric_and_meta_t l2_metric(std::size_t, accuracy_t accuracy) {
|
|
687
722
|
switch (accuracy) {
|
|
688
|
-
case accuracy_t::f8_k: return {pun_metric<f8_bits_t>(
|
|
723
|
+
case accuracy_t::f8_k: return {pun_metric<f8_bits_t>(l2sq_f8_t{}), isa_t::auto_k};
|
|
689
724
|
case accuracy_t::f16_k: return {pun_metric<f16_bits_t>(l2sq_gt<f16_bits_t, f32_t>{}), isa_t::auto_k};
|
|
690
725
|
case accuracy_t::f32_k: return {pun_metric<f32_t>(l2sq_gt<f32_t>{}), isa_t::auto_k};
|
|
691
726
|
case accuracy_t::f64_k: return {pun_metric<f64_t>(l2sq_gt<f64_t>{}), isa_t::auto_k};
|
|
@@ -693,10 +728,10 @@ class auto_index_gt {
|
|
|
693
728
|
}
|
|
694
729
|
}
|
|
695
730
|
|
|
696
|
-
static metric_and_meta_t cos_metric(std::size_t, accuracy_t accuracy) {
|
|
731
|
+
static metric_and_meta_t cos_metric(std::size_t dimensions, accuracy_t accuracy) {
|
|
697
732
|
switch (accuracy) {
|
|
698
|
-
case accuracy_t::f8_k: return {pun_metric<f8_bits_t>(
|
|
699
|
-
case accuracy_t::f16_k: return
|
|
733
|
+
case accuracy_t::f8_k: return {pun_metric<f8_bits_t>(cos_f8_t{}), isa_t::auto_k};
|
|
734
|
+
case accuracy_t::f16_k: return cos_metric_f16(dimensions);
|
|
700
735
|
case accuracy_t::f32_k: return {pun_metric<f32_t>(cos_gt<f32_t>{}), isa_t::auto_k};
|
|
701
736
|
case accuracy_t::f64_k: return {pun_metric<f64_t>(cos_gt<f64_t>{}), isa_t::auto_k};
|
|
702
737
|
default: return {};
|
package/src/bench.cpp
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
#include <variant> // `std::monostate`
|
|
34
34
|
|
|
35
35
|
#include <clipp.h> // Command Line Interface
|
|
36
|
-
#include <omp.h> // `
|
|
36
|
+
#include <omp.h> // `omp_set_num_threads()`
|
|
37
37
|
|
|
38
38
|
#include <simsimd/simsimd.h>
|
|
39
39
|
|
|
@@ -400,7 +400,7 @@ struct args_t {
|
|
|
400
400
|
bool quantize_f16 = false;
|
|
401
401
|
bool quantize_f8 = false;
|
|
402
402
|
|
|
403
|
-
bool metric_ip =
|
|
403
|
+
bool metric_ip = false;
|
|
404
404
|
bool metric_l2 = false;
|
|
405
405
|
bool metric_cos = false;
|
|
406
406
|
bool metric_haversine = false;
|
|
@@ -408,23 +408,19 @@ struct args_t {
|
|
|
408
408
|
|
|
409
409
|
template <typename index_at, typename dataset_at> //
|
|
410
410
|
index_at type_punned_index_for_metric(dataset_at& dataset, args_t const& args, config_t config, accuracy_t accuracy) {
|
|
411
|
-
if (args.metric_ip) {
|
|
412
|
-
std::printf("-- Metric: Inner Product\n");
|
|
413
|
-
return index_at::ip(dataset.dimensions(), accuracy, config);
|
|
414
|
-
}
|
|
415
411
|
if (args.metric_l2) {
|
|
416
412
|
std::printf("-- Metric: Euclidean\n");
|
|
417
413
|
return index_at::l2(dataset.dimensions(), accuracy, config);
|
|
418
|
-
}
|
|
419
|
-
if (args.metric_cos) {
|
|
414
|
+
} else if (args.metric_cos) {
|
|
420
415
|
std::printf("-- Metric: Angular\n");
|
|
421
416
|
return index_at::cos(dataset.dimensions(), accuracy, config);
|
|
422
|
-
}
|
|
423
|
-
if (args.metric_haversine) {
|
|
417
|
+
} else if (args.metric_haversine) {
|
|
424
418
|
std::printf("-- Metric: Haversine\n");
|
|
425
419
|
return index_at::haversine(accuracy, config);
|
|
420
|
+
} else {
|
|
421
|
+
std::printf("-- Metric: Inner Product\n");
|
|
422
|
+
return index_at::ip(dataset.dimensions(), accuracy, config);
|
|
426
423
|
}
|
|
427
|
-
throw std::invalid_argument("Unknown metric!");
|
|
428
424
|
}
|
|
429
425
|
|
|
430
426
|
template <typename index_at, typename dataset_at> //
|
|
@@ -472,16 +468,16 @@ template <typename neighbor_id_at, typename dataset_at> //
|
|
|
472
468
|
void run_big_or_small(dataset_at& dataset, args_t const& args, config_t config) {
|
|
473
469
|
if (args.native) {
|
|
474
470
|
if (args.metric_cos) {
|
|
475
|
-
std::printf("-- Metric:
|
|
476
|
-
run_typed<index_gt<
|
|
471
|
+
std::printf("-- Metric: Angular\n");
|
|
472
|
+
run_typed<index_gt<cos_gt<float>, std::size_t, neighbor_id_at>>(dataset, args, config);
|
|
477
473
|
} else if (args.metric_l2) {
|
|
478
474
|
std::printf("-- Metric: Euclidean\n");
|
|
479
475
|
run_typed<index_gt<l2sq_gt<float>, std::size_t, neighbor_id_at>>(dataset, args, config);
|
|
480
476
|
} else if (args.metric_haversine) {
|
|
481
|
-
std::printf("-- Metric:
|
|
477
|
+
std::printf("-- Metric: Haversine\n");
|
|
482
478
|
run_typed<index_gt<haversine_gt<float>, std::size_t, neighbor_id_at>>(dataset, args, config);
|
|
483
479
|
} else {
|
|
484
|
-
std::printf("-- Metric:
|
|
480
|
+
std::printf("-- Metric: Inner Product\n");
|
|
485
481
|
run_typed<index_gt<ip_gt<float>, std::size_t, neighbor_id_at>>(dataset, args, config);
|
|
486
482
|
}
|
|
487
483
|
} else
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"devDependencies": {
|
|
3
|
-
"@semantic-release/exec": "github:semantic-release/exec",
|
|
4
|
-
"@semantic-release/git": "^10.0.1",
|
|
5
|
-
"conventional-changelog-eslint": "^3.0.9",
|
|
6
|
-
"semantic-release": "^20.1.3"
|
|
7
|
-
},
|
|
8
|
-
"release": {
|
|
9
|
-
"branches": [
|
|
10
|
-
"main"
|
|
11
|
-
],
|
|
12
|
-
"debug": true,
|
|
13
|
-
"ci": true,
|
|
14
|
-
"dryRun": false,
|
|
15
|
-
"plugins": [
|
|
16
|
-
[
|
|
17
|
-
"@semantic-release/commit-analyzer",
|
|
18
|
-
{
|
|
19
|
-
"preset": "eslint",
|
|
20
|
-
"releaseRules": [
|
|
21
|
-
{
|
|
22
|
-
"tag": "Add",
|
|
23
|
-
"release": "minor"
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"tag": "Improve",
|
|
27
|
-
"release": "patch"
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
"tag": "Make",
|
|
31
|
-
"release": "patch"
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
"tag": "Refactor",
|
|
35
|
-
"release": false
|
|
36
|
-
}
|
|
37
|
-
]
|
|
38
|
-
}
|
|
39
|
-
],
|
|
40
|
-
[
|
|
41
|
-
"@semantic-release/release-notes-generator",
|
|
42
|
-
{
|
|
43
|
-
"preset": "eslint",
|
|
44
|
-
"releaseRules": [
|
|
45
|
-
{
|
|
46
|
-
"tag": "Add",
|
|
47
|
-
"release": "minor"
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
"tag": "Improve",
|
|
51
|
-
"release": "patch"
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
"tag": "Make",
|
|
55
|
-
"release": "patch"
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
"tag": "Refactor",
|
|
59
|
-
"release": false
|
|
60
|
-
}
|
|
61
|
-
]
|
|
62
|
-
}
|
|
63
|
-
],
|
|
64
|
-
"@semantic-release/github",
|
|
65
|
-
[
|
|
66
|
-
"@semantic-release/exec",
|
|
67
|
-
{
|
|
68
|
-
"prepareCmd": "echo '${nextRelease.version}' > VERSION"
|
|
69
|
-
}
|
|
70
|
-
],
|
|
71
|
-
[
|
|
72
|
-
"@semantic-release/git",
|
|
73
|
-
{
|
|
74
|
-
"assets": [
|
|
75
|
-
"VERSION"
|
|
76
|
-
],
|
|
77
|
-
"message": "Build: Released ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
|
78
|
-
}
|
|
79
|
-
]
|
|
80
|
-
]
|
|
81
|
-
}
|
|
82
|
-
}
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
# Compiling USearch
|
|
2
|
-
|
|
3
|
-
## Build
|
|
4
|
-
|
|
5
|
-
Before building the first time, please pull submodules.
|
|
6
|
-
|
|
7
|
-
```sh
|
|
8
|
-
git submodule update --init --recursive
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
### Linux
|
|
12
|
-
|
|
13
|
-
```sh
|
|
14
|
-
cmake -B ./build_release \
|
|
15
|
-
-DCMAKE_CXX_COMPILER="g++-12" \
|
|
16
|
-
-DCMAKE_BUILD_TYPE=Release \
|
|
17
|
-
-DUSEARCH_USE_SIMD=1 \
|
|
18
|
-
-DUSEARCH_USE_OPENMP=1 \
|
|
19
|
-
-DUSEARCH_USE_JEMALLOC=1 && \
|
|
20
|
-
make -C ./build_release -j
|
|
21
|
-
|
|
22
|
-
# To benchmark in C++:
|
|
23
|
-
./build_release/bench \
|
|
24
|
-
--vectors datasets/wiki_1M/base.1M.fbin \
|
|
25
|
-
--queries datasets/wiki_1M/query.public.100K.fbin \
|
|
26
|
-
--neighbors datasets/wiki_1M/groundtruth.public.100K.ibin
|
|
27
|
-
|
|
28
|
-
# Large benchmark on a 1TB dataset:
|
|
29
|
-
./build_release/bench \
|
|
30
|
-
--vectors datasets/t2i_1B/base.1B.fbin \
|
|
31
|
-
--queries datasets/t2i_1B/query.public.100K.fbin \
|
|
32
|
-
--neighbors datasets/t2i_1B/groundtruth.public.100K.ibin \
|
|
33
|
-
--output datasets/t2i_1B/index.usearch \
|
|
34
|
-
--cos
|
|
35
|
-
|
|
36
|
-
# To benchmark in Python:
|
|
37
|
-
python python/bench.py \
|
|
38
|
-
--vectors datasets/wiki_1M/base.1M.fbin \
|
|
39
|
-
--queries datasets/wiki_1M/query.public.100K.fbin \
|
|
40
|
-
--neighbors datasets/wiki_1M/groundtruth.public.100K.ibin
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### MacOS
|
|
44
|
-
|
|
45
|
-
```sh
|
|
46
|
-
brew install libomp llvm
|
|
47
|
-
cmake \
|
|
48
|
-
-DCMAKE_C_COMPILER="/opt/homebrew/opt/llvm/bin/clang" \
|
|
49
|
-
-DCMAKE_CXX_COMPILER="/opt/homebrew/opt/llvm/bin/clang++" \
|
|
50
|
-
-DUSEARCH_USE_SIMD=1 \
|
|
51
|
-
-DUSEARCH_USE_OPENMP=1 \
|
|
52
|
-
-B ./build_release && \
|
|
53
|
-
make -C ./build_release -j
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### Python
|
|
57
|
-
|
|
58
|
-
```sh
|
|
59
|
-
pip install -e .
|
|
60
|
-
python python/test.py
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### JavaScript
|
|
64
|
-
|
|
65
|
-
```sh
|
|
66
|
-
npm install
|
|
67
|
-
node javascript/test.js
|
|
68
|
-
npm publish
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### Rust
|
|
72
|
-
|
|
73
|
-
```sh
|
|
74
|
-
cargo test -p usearch
|
|
75
|
-
cargo publish
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### Java
|
|
79
|
-
|
|
80
|
-
```sh
|
|
81
|
-
gradle clean build
|
|
82
|
-
java -cp . -Djava.library.path=/Users/av/github/usearch/build/libs/usearch/shared java/cloud/unum/usearch/Index.java
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
Or step by-step:
|
|
86
|
-
|
|
87
|
-
```sh
|
|
88
|
-
cs java/unum/cloud/usearch
|
|
89
|
-
javac -h . Index.java
|
|
90
|
-
|
|
91
|
-
# Ubuntu:
|
|
92
|
-
g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
|
|
93
|
-
g++ -shared -fPIC -o libusearch.so cloud_unum_usearch_Index.o -lc
|
|
94
|
-
|
|
95
|
-
# Windows
|
|
96
|
-
g++ -c -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
|
|
97
|
-
g++ -shared -o USearchJNI.dll cloud_unum_usearch_Index.o -Wl,--add-stdcall-alias
|
|
98
|
-
|
|
99
|
-
# MacOS
|
|
100
|
-
g++ -std=c++11 -c -fPIC \
|
|
101
|
-
-I../../../../include -I../../../../src -I../../../../fp16/include -I../../../../simsimd/include \
|
|
102
|
-
-I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
|
|
103
|
-
g++ -dynamiclib -o libusearch.dylib cloud_unum_usearch_Index.o -lc
|
|
104
|
-
# Run linking to that directory
|
|
105
|
-
java -cp . -Djava.library.path=/Users/av/github/usearch/java/cloud/unum/usearch/ Index.java
|
|
106
|
-
java -cp . -Djava.library.path=/Users/av/github/usearch/java cloud.unum.usearch.Index
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### Wolfram
|
|
110
|
-
|
|
111
|
-
```sh
|
|
112
|
-
brew install --cask wolfram-engine
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
## Benchmarks
|
|
116
|
-
|
|
117
|
-
### Datasets
|
|
118
|
-
|
|
119
|
-
BigANN benchmark is a good starting point, if you are searching for large collections of high-dimensional vectors.
|
|
120
|
-
Those often come with precomputed ground-truth neighbors, which is handy for recall evaluation.
|
|
121
|
-
|
|
122
|
-
| Dataset | Scalar Type | Dimensions | Metric | Size |
|
|
123
|
-
| :-------------------------------------- | :---------: | :--------: | :----: | :-------: |
|
|
124
|
-
| [Unum UForm Wiki][unum-wiki] | float32 | 256 | IP | 1 GB |
|
|
125
|
-
| [Yandex Text-to-Image Sample][unum-t2i] | float32 | 200 | Cos | 1 GB |
|
|
126
|
-
| | | | | |
|
|
127
|
-
| [Microsoft SPACEV][spacev] | int8 | 100 | L2 | 93 GB |
|
|
128
|
-
| [Microsoft Turing-ANNS][turing] | float32 | 100 | L2 | 373 GB |
|
|
129
|
-
| [Yandex Deep1B][deep] | float32 | 96 | L2 | 358 GB |
|
|
130
|
-
| [Yandex Text-to-Image][t2i] | float32 | 200 | Cos | 750 GB |
|
|
131
|
-
| | | | | |
|
|
132
|
-
| [ViT-L/12 LAION][laion] | float32 | 2048 | Cos | 2 - 10 TB |
|
|
133
|
-
|
|
134
|
-
Luckily, smaller samples of those datasets are available.
|
|
135
|
-
|
|
136
|
-
[unum-wiki]: https://huggingface.co/datasets/unum-cloud/ann-wiki-1m
|
|
137
|
-
[unum-t2i]: https://huggingface.co/datasets/unum-cloud/ann-t2i-1m
|
|
138
|
-
[spacev]: https://github.com/microsoft/SPTAG/tree/main/datasets/SPACEV1B
|
|
139
|
-
[turing]: https://learning2hash.github.io/publications/microsoftturinganns1B/
|
|
140
|
-
[t2i]: https://research.yandex.com/blog/benchmarks-for-billion-scale-similarity-search
|
|
141
|
-
[deep]: https://research.yandex.com/blog/benchmarks-for-billion-scale-similarity-search
|
|
142
|
-
[laion]: https://laion.ai/blog/laion-5b/#download-the-data
|
|
143
|
-
|
|
144
|
-
### Unum UForm Wiki
|
|
145
|
-
|
|
146
|
-
```sh
|
|
147
|
-
mkdir -p datasets/wiki_1M/ && \
|
|
148
|
-
wget -nc https://huggingface.co/datasets/unum-cloud/ann-wiki-1m/resolve/main/base.1M.fbin -P datasets/wiki_1M/ &&
|
|
149
|
-
wget -nc https://huggingface.co/datasets/unum-cloud/ann-wiki-1m/resolve/main/query.public.100K.fbin -P datasets/wiki_1M/ &&
|
|
150
|
-
wget -nc https://huggingface.co/datasets/unum-cloud/ann-wiki-1m/resolve/main/groundtruth.public.100K.ibin -P datasets/wiki_1M/
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
### Yandex Text-to-Image
|
|
154
|
-
|
|
155
|
-
```sh
|
|
156
|
-
mkdir -p datasets/t2i_1B/ && \
|
|
157
|
-
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/T2I/base.1B.fbin -P datasets/t2i_1B/ &&
|
|
158
|
-
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/T2I/base.1M.fbin -P datasets/t2i_1B/ &&
|
|
159
|
-
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/T2I/query.public.100K.fbin -P datasets/t2i_1B/ &&
|
|
160
|
-
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/T2I/groundtruth.public.100K.ibin -P datasets/t2i_1B/
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
### Yandex Deep1B
|
|
164
|
-
|
|
165
|
-
```sh
|
|
166
|
-
mkdir -p datasets/deep_1B/ && \
|
|
167
|
-
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/base.1B.fbin -P datasets/deep_1B/ &&
|
|
168
|
-
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/base.10M.fbin -P datasets/deep_1B/ &&
|
|
169
|
-
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/query.public.10K.fbin -P datasets/deep_1B/ &&
|
|
170
|
-
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/groundtruth.public.10K.ibin -P datasets/deep_1B/
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
### Profiling
|
|
174
|
-
|
|
175
|
-
With `perf`:
|
|
176
|
-
|
|
177
|
-
```sh
|
|
178
|
-
# Pass environment variables with `-E`, and `-d` for details
|
|
179
|
-
sudo -E perf stat -d ./build_release/bench ...
|
|
180
|
-
sudo -E perf mem -d ./build_release/bench ...
|
|
181
|
-
# Sample on-CPU functions for the specified command, at 1 Kilo Hertz:
|
|
182
|
-
sudo -E perf record -F 1000 ./build_release/bench ...
|
|
183
|
-
perf record -d -e arm_spe// -- ./build_release/bench ..
|
|
184
|
-
```
|
|
185
|
-
|