usearch 0.13.0 → 0.15.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/.github/workflows/release.yml +62 -7
- package/.github/workflows/update_version.sh +6 -1
- package/.vscode/launch.json +21 -22
- package/.vscode/settings.json +7 -1
- package/CITATION.cff +4 -4
- package/CMakeLists.txt +1 -1
- package/Cargo.toml +1 -1
- package/Package.swift +0 -1
- package/README.md +100 -27
- package/binding.gyp +0 -1
- package/build.gradle +1 -1
- package/build.rs +3 -3
- package/c/lib.cpp +32 -9
- package/c/usearch.h +67 -36
- package/conanfile.py +1 -1
- package/{src → cpp}/bench.cpp +52 -36
- package/{src → cpp}/test.cpp +17 -7
- package/docs/benchmarks.md +33 -10
- package/docs/c/index.rst +11 -0
- package/docs/c/reference.rst +7 -0
- package/docs/compilation.md +24 -8
- package/docs/conf.dox +6 -6
- package/docs/conf.py +3 -1
- package/docs/cpp/index.rst +11 -0
- package/docs/cpp/reference.rst +7 -0
- package/docs/index.rst +10 -0
- package/docs/java/index.rst +11 -0
- package/docs/java/reference.rst +7 -0
- package/docs/javascript/index.rst +11 -0
- package/docs/javascript/reference.rst +9 -0
- package/docs/python/index.rst +11 -0
- package/docs/python/reference.rst +35 -0
- package/golang/lib.go +1 -1
- package/include/usearch/{usearch.hpp → index.hpp} +152 -148
- package/include/usearch/index_punned_dense.hpp +633 -0
- package/include/usearch/index_punned_helpers.hpp +528 -0
- package/java/cloud/unum/usearch/cloud_unum_usearch_Index.cpp +8 -7
- package/javascript/lib.cpp +26 -50
- package/javascript/usearch.js +117 -2
- package/objc/USearchObjective.mm +145 -49
- package/objc/include/USearchObjective.h +106 -30
- package/package.json +2 -2
- package/python/lib.cpp +178 -320
- package/python/scripts/bench.ipynb +170 -0
- package/python/scripts/bench.py +102 -185
- package/python/scripts/index_faiss.py +100 -0
- package/python/scripts/test.py +57 -34
- package/python/usearch/eval.py +353 -0
- package/python/usearch/index.py +138 -117
- package/python/usearch/io.py +7 -2
- package/python/usearch/join.py +100 -0
- package/python/usearch/numba.py +101 -0
- package/rust/lib.cpp +27 -14
- package/rust/lib.hpp +4 -10
- package/rust/lib.rs +50 -17
- package/setup.py +12 -2
- package/simsimd/include/simsimd/simsimd.h +32 -3
- package/swift/Index+Sugar.swift +55 -29
- package/swift/Test.swift +1 -1
- package/wolfram/lib.cpp +4 -4
- package/python/scripts/bench_params.py +0 -161
- package/python/usearch/synthetic.py +0 -32
- package/src/punned.hpp +0 -887
- /package/{src → cpp}/CMakeLists.txt +0 -0
package/c/usearch.h
CHANGED
|
@@ -1,43 +1,74 @@
|
|
|
1
1
|
#ifndef UNUM_USEARCH_H
|
|
2
2
|
#define UNUM_USEARCH_H
|
|
3
3
|
|
|
4
|
-
#include <
|
|
4
|
+
#include <stdint.h> // `size_t`
|
|
5
5
|
|
|
6
|
-
typedef
|
|
6
|
+
typedef void* usearch_index_t;
|
|
7
|
+
typedef uint32_t usearch_label_t;
|
|
8
|
+
typedef char const* usearch_error_t;
|
|
9
|
+
|
|
10
|
+
typedef float (*)(void const*, void const*) usearch_metric_t;
|
|
11
|
+
|
|
12
|
+
typedef enum usearch_metric_kind_t {
|
|
7
13
|
usearch_metric_ip_k = 0,
|
|
8
|
-
usearch_metric_l2sq_k
|
|
9
|
-
usearch_metric_cos_k
|
|
10
|
-
usearch_metric_haversine_k
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
14
|
+
usearch_metric_l2sq_k,
|
|
15
|
+
usearch_metric_cos_k,
|
|
16
|
+
usearch_metric_haversine_k,
|
|
17
|
+
usearch_metric_pearson_k,
|
|
18
|
+
usearch_metric_jaccard_k,
|
|
19
|
+
usearch_metric_hamming_k,
|
|
20
|
+
usearch_metric_tanimoto_k,
|
|
21
|
+
usearch_metric_sorensen_k,
|
|
22
|
+
usearch_metric_unknown_k,
|
|
23
|
+
} usearch_metric_kind_t;
|
|
24
|
+
|
|
25
|
+
typedef enum usearch_scalar_kind_t {
|
|
26
|
+
usearch_scalar_f32_k = 0,
|
|
27
|
+
usearch_scalar_f64_k,
|
|
28
|
+
usearch_scalar_f16_k,
|
|
29
|
+
usearch_scalar_f8_k,
|
|
30
|
+
usearch_scalar_b1_k,
|
|
31
|
+
usearch_scalar_unknown_k,
|
|
32
|
+
} usearch_scalar_kind_t;
|
|
33
|
+
|
|
34
|
+
typedef struct usearch_init_options_t {
|
|
35
|
+
|
|
36
|
+
usearch_metric_kind_t metric_kind;
|
|
37
|
+
usearch_metric_t metric;
|
|
38
|
+
|
|
39
|
+
usearch_scalar_kind_t quantization;
|
|
40
|
+
size_t dimensions;
|
|
41
|
+
size_t capacity;
|
|
42
|
+
size_t connectivity;
|
|
43
|
+
size_t expansion_add;
|
|
44
|
+
size_t expansion_search;
|
|
45
|
+
} usearch_init_options_t;
|
|
46
|
+
|
|
47
|
+
void usearch_init(usearch_init_options_t*, usearch_index_t*, usearch_error_t*);
|
|
48
|
+
void usearch_free(usearch_index_t, usearch_error_t*);
|
|
49
|
+
|
|
50
|
+
void usearch_save(usearch_index_t, char const* path, usearch_error_t*);
|
|
51
|
+
void usearch_load(usearch_index_t, char const* path, usearch_error_t*);
|
|
52
|
+
void usearch_view(usearch_index_t, char const* path, usearch_error_t*);
|
|
53
|
+
|
|
54
|
+
size_t usearch_size(usearch_index_t, usearch_error_t*);
|
|
55
|
+
size_t usearch_capacity(usearch_index_t, usearch_error_t*);
|
|
56
|
+
size_t usearch_dimensions(usearch_index_t, usearch_error_t*);
|
|
57
|
+
size_t usearch_connectivity(usearch_index_t, usearch_error_t*);
|
|
58
|
+
|
|
59
|
+
void usearch_reserve(usearch_index_t, size_t capacity, usearch_error_t*);
|
|
60
|
+
void usearch_add(usearch_index_t, usearch_label_t, float const* vector, usearch_error_t*);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @brief Performs k-Approximate Nearest Neighbors Search.
|
|
64
|
+
* @return Number of found matches.
|
|
65
|
+
*/
|
|
66
|
+
size_t usearch_search( //
|
|
67
|
+
usearch_index_t, float const* query_vector, size_t results_limit, //
|
|
68
|
+
usearch_label_t* found_labels, float* found_distances, usearch_error_t*);
|
|
69
|
+
|
|
70
|
+
bool usearch_contains(usearch_index_t, usearch_label_t, usearch_error_t*);
|
|
71
|
+
void usearch_get(usearch_index_t, usearch_label_t, float* vector, usearch_error_t*);
|
|
72
|
+
void usearch_remove(usearch_index_t, usearch_label_t, usearch_error_t*);
|
|
42
73
|
|
|
43
74
|
#endif
|
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.15.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/{src → cpp}/bench.cpp
RENAMED
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
#include <simsimd/simsimd.h>
|
|
40
40
|
|
|
41
|
-
#include
|
|
41
|
+
#include <usearch/index_punned_dense.hpp>
|
|
42
42
|
|
|
43
43
|
using namespace unum::usearch;
|
|
44
44
|
using namespace unum;
|
|
@@ -432,46 +432,58 @@ struct args_t {
|
|
|
432
432
|
|
|
433
433
|
bool big = false;
|
|
434
434
|
bool native = false;
|
|
435
|
+
|
|
435
436
|
bool quantize_f16 = false;
|
|
436
437
|
bool quantize_f8 = false;
|
|
438
|
+
bool quantize_b1 = false;
|
|
437
439
|
|
|
438
440
|
bool metric_ip = false;
|
|
439
441
|
bool metric_l2 = false;
|
|
440
442
|
bool metric_cos = false;
|
|
441
443
|
bool metric_haversine = false;
|
|
442
|
-
|
|
444
|
+
bool metric_hamming = false;
|
|
445
|
+
bool metric_tanimoto = false;
|
|
446
|
+
bool metric_sorensen = false;
|
|
447
|
+
|
|
448
|
+
metric_kind_t metric() const noexcept {
|
|
449
|
+
if (metric_l2)
|
|
450
|
+
return metric_kind_t::l2sq_k;
|
|
451
|
+
if (metric_cos)
|
|
452
|
+
return metric_kind_t::cos_k;
|
|
453
|
+
if (metric_haversine)
|
|
454
|
+
return metric_kind_t::haversine_k;
|
|
455
|
+
if (metric_hamming)
|
|
456
|
+
return metric_kind_t::hamming_k;
|
|
457
|
+
if (metric_tanimoto)
|
|
458
|
+
return metric_kind_t::tanimoto_k;
|
|
459
|
+
if (metric_sorensen)
|
|
460
|
+
return metric_kind_t::sorensen_k;
|
|
461
|
+
return metric_kind_t::ip_k;
|
|
462
|
+
}
|
|
443
463
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
return
|
|
452
|
-
} else if (args.metric_haversine) {
|
|
453
|
-
std::printf("-- Metric: Haversine\n");
|
|
454
|
-
return index_at::haversine(accuracy, config);
|
|
455
|
-
} else {
|
|
456
|
-
std::printf("-- Metric: Inner Product\n");
|
|
457
|
-
return index_at::ip(dataset.dimensions(), accuracy, config);
|
|
464
|
+
scalar_kind_t accuracy() const noexcept {
|
|
465
|
+
if (quantize_f16)
|
|
466
|
+
return scalar_kind_t::f16_k;
|
|
467
|
+
if (quantize_f8)
|
|
468
|
+
return scalar_kind_t::f8_k;
|
|
469
|
+
if (quantize_b1)
|
|
470
|
+
return scalar_kind_t::b1x8_k;
|
|
471
|
+
return scalar_kind_t::f32_k;
|
|
458
472
|
}
|
|
459
|
-
}
|
|
473
|
+
};
|
|
460
474
|
|
|
461
475
|
template <typename index_at, typename dataset_at> //
|
|
462
476
|
void run_punned(dataset_at& dataset, args_t const& args, index_config_t config, index_limits_t limits) {
|
|
463
477
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
accuracy = accuracy_t::f16_k;
|
|
467
|
-
if (args.quantize_f8)
|
|
468
|
-
accuracy = accuracy_t::f8_k;
|
|
478
|
+
scalar_kind_t accuracy = args.accuracy();
|
|
479
|
+
std::printf("-- Accuracy: %s\n", scalar_kind_name(accuracy));
|
|
469
480
|
|
|
470
|
-
|
|
481
|
+
metric_kind_t kind = args.metric();
|
|
482
|
+
std::printf("-- Metric: %s\n", metric_kind_name(kind));
|
|
471
483
|
|
|
472
|
-
index_at index
|
|
484
|
+
index_at index = index_at::make(dataset.dimensions(), kind, config, accuracy);
|
|
473
485
|
index.reserve(limits);
|
|
474
|
-
std::printf("-- Hardware acceleration: %s\n", isa_name(index.
|
|
486
|
+
std::printf("-- Hardware acceleration: %s\n", isa_name(index.isa()));
|
|
475
487
|
std::printf("Will benchmark in-memory\n");
|
|
476
488
|
|
|
477
489
|
single_shot(dataset, index, true);
|
|
@@ -518,7 +530,7 @@ void run_big_or_small(dataset_at& dataset, args_t const& args, index_config_t co
|
|
|
518
530
|
run_typed<index_gt<ip_gt<float>, std::size_t, neighbor_id_at>>(dataset, args, config, limits);
|
|
519
531
|
}
|
|
520
532
|
} else
|
|
521
|
-
run_punned<
|
|
533
|
+
run_punned<index_punned_dense_gt<std::size_t, neighbor_id_at>>(dataset, args, config, limits);
|
|
522
534
|
}
|
|
523
535
|
|
|
524
536
|
void report_alternative_setups() {
|
|
@@ -537,8 +549,8 @@ void report_expected_losses(persisted_dataset_gt<float, vector_id_t> const& data
|
|
|
537
549
|
|
|
538
550
|
auto vec1 = dataset.vector(0);
|
|
539
551
|
auto vec2 = dataset.query(0);
|
|
540
|
-
std::vector<
|
|
541
|
-
std::vector<
|
|
552
|
+
std::vector<f16_t> vec1f16(dataset.dimensions());
|
|
553
|
+
std::vector<f16_t> vec2f16(dataset.dimensions());
|
|
542
554
|
std::transform(vec1, vec1 + dataset.dimensions(), vec1f16.data(), [](float v) { return v; });
|
|
543
555
|
std::transform(vec2, vec2 + dataset.dimensions(), vec2f16.data(), [](float v) { return v; });
|
|
544
556
|
std::vector<f8_bits_t> vec1f8(dataset.dimensions());
|
|
@@ -548,7 +560,7 @@ void report_expected_losses(persisted_dataset_gt<float, vector_id_t> const& data
|
|
|
548
560
|
|
|
549
561
|
#if 0
|
|
550
562
|
auto ip_default = ip_gt<float>{}(vec1, vec2, dataset.dimensions());
|
|
551
|
-
auto ip_f16 = ip_gt<
|
|
563
|
+
auto ip_f16 = ip_gt<f16_t, float>{}(vec1f16.data(), vec2f16.data(), dataset.dimensions());
|
|
552
564
|
auto ip_f8 = ip_gt<f8_bits_t, float>{}(vec1f8.data(), vec2f8.data(), dataset.dimensions());
|
|
553
565
|
|
|
554
566
|
#if defined(__AVX512F__)
|
|
@@ -591,12 +603,16 @@ int main(int argc, char** argv) {
|
|
|
591
603
|
(option("--rows-take") & value("integer", args.vectors_to_take)).doc("Number of vectors to take"),
|
|
592
604
|
( //
|
|
593
605
|
option("--native").set(args.native).doc("Use raw templates instead of type-punned classes") |
|
|
594
|
-
option("--f16quant").set(args.quantize_f16).doc("Enable `f16_t` quantization") |
|
|
595
|
-
option("--f8quant").set(args.quantize_f8).doc("Enable `f8_t` quantization")
|
|
606
|
+
option("-f16", "--f16quant").set(args.quantize_f16).doc("Enable `f16_t` quantization") |
|
|
607
|
+
option("-f8", "--f8quant").set(args.quantize_f8).doc("Enable `f8_t` quantization") |
|
|
608
|
+
option("-b1", "--b1quant").set(args.quantize_b1).doc("Enable `b1x8_t` quantization")),
|
|
596
609
|
( //
|
|
597
610
|
option("--ip").set(args.metric_ip).doc("Choose Inner Product metric") |
|
|
598
611
|
option("--l2sq").set(args.metric_l2).doc("Choose L2 Euclidean metric") |
|
|
599
612
|
option("--cos").set(args.metric_cos).doc("Choose Angular metric") |
|
|
613
|
+
option("--hamming").set(args.metric_hamming).doc("Choose Hamming metric") |
|
|
614
|
+
option("--tanimoto").set(args.metric_tanimoto).doc("Choose Tanimoto metric") |
|
|
615
|
+
option("--sorensen").set(args.metric_sorensen).doc("Choose Sorensen metric") |
|
|
600
616
|
option("--haversine").set(args.metric_haversine).doc("Choose Haversine metric")),
|
|
601
617
|
option("-h", "--help").set(args.help).doc("Print this help information on this tool and exit"));
|
|
602
618
|
|
|
@@ -609,7 +625,7 @@ int main(int argc, char** argv) {
|
|
|
609
625
|
exit(0);
|
|
610
626
|
}
|
|
611
627
|
|
|
612
|
-
// Instead of relying on `multithreaded` from "
|
|
628
|
+
// Instead of relying on `multithreaded` from "index_punned_dense.hpp" we will use OpenMP
|
|
613
629
|
// to better estimate statistics between tasks batches, without having to recreate
|
|
614
630
|
// the threads.
|
|
615
631
|
omp_set_dynamic(true);
|
|
@@ -638,16 +654,16 @@ int main(int argc, char** argv) {
|
|
|
638
654
|
|
|
639
655
|
index_config_t config;
|
|
640
656
|
config.connectivity = args.connectivity;
|
|
641
|
-
config.expansion_add = args.expansion_add;
|
|
642
|
-
config.expansion_search = args.expansion_search;
|
|
657
|
+
// config.expansion_add = args.expansion_add;
|
|
658
|
+
// config.expansion_search = args.expansion_search;
|
|
643
659
|
index_limits_t limits;
|
|
644
660
|
limits.threads_add = limits.threads_search = args.threads;
|
|
645
661
|
limits.elements = dataset.vectors_count();
|
|
646
662
|
|
|
647
663
|
std::printf("- Index: \n");
|
|
648
664
|
std::printf("-- Connectivity: %zu\n", config.connectivity);
|
|
649
|
-
std::printf("-- Expansion @ Add: %zu\n", config.expansion_add);
|
|
650
|
-
std::printf("-- Expansion @ Search: %zu\n", config.expansion_search);
|
|
665
|
+
// std::printf("-- Expansion @ Add: %zu\n", config.expansion_add);
|
|
666
|
+
// std::printf("-- Expansion @ Search: %zu\n", config.expansion_search);
|
|
651
667
|
|
|
652
668
|
if (args.big)
|
|
653
669
|
run_big_or_small<uint40_t>(dataset, args, config, limits);
|
package/{src → cpp}/test.cpp
RENAMED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
#include <algorithm>
|
|
5
5
|
#include <stdexcept>
|
|
6
6
|
|
|
7
|
-
#include
|
|
7
|
+
#include <usearch/index_punned_dense.hpp>
|
|
8
8
|
|
|
9
9
|
using namespace unum::usearch;
|
|
10
10
|
using namespace unum;
|
|
@@ -134,20 +134,30 @@ template <typename index_at> void test_sets_moved() {
|
|
|
134
134
|
|
|
135
135
|
int main(int, char**) {
|
|
136
136
|
|
|
137
|
+
static_assert(!std::is_same<index_gt<ip_gt<>>::value_type, std::true_type>());
|
|
138
|
+
static_assert(!std::is_same<index_gt<cos_gt<>>::value_type, std::true_type>());
|
|
139
|
+
static_assert(!std::is_same<index_gt<l2sq_gt<>>::value_type, std::true_type>());
|
|
140
|
+
// static_assert(!std::is_same<index_gt<hamming_gt<>>::value_type, std::true_type>());
|
|
141
|
+
// static_assert(!std::is_same<index_gt<tanimoto_gt<>>::value_type, std::true_type>());
|
|
142
|
+
// static_assert(!std::is_same<index_gt<sorensen_gt<>>::value_type, std::true_type>());
|
|
143
|
+
// static_assert(!std::is_same<index_gt<jaccard_gt<>>::value_type, std::true_type>());
|
|
144
|
+
// static_assert(!std::is_same<index_gt<pearson_correlation_gt<>>::value_type, std::true_type>());
|
|
145
|
+
// static_assert(!std::is_same<index_gt<haversine_gt<>>::value_type, std::true_type>());
|
|
146
|
+
|
|
137
147
|
test3d<float>(index_gt<cos_gt<float>, point_id_t, std::uint32_t, float>{});
|
|
138
148
|
test3d<float>(index_gt<l2sq_gt<float>, point_id_t, std::uint32_t, float>{});
|
|
139
149
|
|
|
140
150
|
test3d<double>(index_gt<cos_gt<double>, point_id_t, std::uint32_t, double>{});
|
|
141
151
|
test3d<double>(index_gt<l2sq_gt<double>, point_id_t, std::uint32_t, double>{});
|
|
142
152
|
|
|
143
|
-
test3d<float>(punned_small_t::
|
|
144
|
-
test3d<float>(punned_small_t::
|
|
153
|
+
test3d<float>(punned_small_t::make(3, metric_kind_t::cos_k));
|
|
154
|
+
test3d<float>(punned_small_t::make(3, metric_kind_t::l2sq_k));
|
|
145
155
|
|
|
146
|
-
test3d<double>(punned_small_t::
|
|
147
|
-
test3d<double>(punned_small_t::
|
|
156
|
+
test3d<double>(punned_small_t::make(3, metric_kind_t::cos_k));
|
|
157
|
+
test3d<double>(punned_small_t::make(3, metric_kind_t::l2sq_k));
|
|
148
158
|
|
|
149
|
-
test3d_punned<float>(punned_small_t::
|
|
150
|
-
test3d_punned<float>(punned_small_t::
|
|
159
|
+
test3d_punned<float>(punned_small_t::make(3, metric_kind_t::cos_k));
|
|
160
|
+
test3d_punned<float>(punned_small_t::make(3, metric_kind_t::l2sq_k));
|
|
151
161
|
|
|
152
162
|
test_sets(index_gt<jaccard_gt<std::int32_t, float>, point_id_t, std::uint32_t, std::int32_t>{});
|
|
153
163
|
test_sets(index_gt<jaccard_gt<std::int64_t, float>, point_id_t, std::uint32_t, std::int64_t>{});
|
package/docs/benchmarks.md
CHANGED
|
@@ -55,7 +55,7 @@ Also worth noting, 8-bit quantization results in almost no accuracy loss and may
|
|
|
55
55
|
|
|
56
56
|
Within this repository you will find two commonly used utilities:
|
|
57
57
|
|
|
58
|
-
- `
|
|
58
|
+
- `cpp/bench.cpp` the produces the `bench` binary for broad USearch benchmarks.
|
|
59
59
|
- `python/bench.py` for simple benchmarks against FAISS.
|
|
60
60
|
|
|
61
61
|
To achieve best highest results we suggest compiling locally for the target architecture.
|
|
@@ -170,15 +170,6 @@ mkdir -p datasets/deep_1B/ && \
|
|
|
170
170
|
|
|
171
171
|
## Profiling
|
|
172
172
|
|
|
173
|
-
Enabling Huge Pages:
|
|
174
|
-
|
|
175
|
-
```sh
|
|
176
|
-
sudo cat /proc/sys/vm/nr_hugepages
|
|
177
|
-
sudo sysctl -w vm.nr_hugepages=2048
|
|
178
|
-
sudo reboot
|
|
179
|
-
sudo cat /proc/sys/vm/nr_hugepages
|
|
180
|
-
```
|
|
181
|
-
|
|
182
173
|
With `perf`:
|
|
183
174
|
|
|
184
175
|
```sh
|
|
@@ -189,3 +180,35 @@ sudo -E perf mem -d ./build_release/bench ...
|
|
|
189
180
|
sudo -E perf record -F 1000 ./build_release/bench ...
|
|
190
181
|
perf record -d -e arm_spe// -- ./build_release/bench ..
|
|
191
182
|
```
|
|
183
|
+
|
|
184
|
+
### Caches
|
|
185
|
+
|
|
186
|
+
```sh
|
|
187
|
+
sudo perf stat -e 'faults,dTLB-loads,dTLB-load-misses,cache-misses,cache-references' ./build_release/bench ...
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Typical output on a 1M vectors dataset is:
|
|
191
|
+
|
|
192
|
+
```txt
|
|
193
|
+
255426 faults
|
|
194
|
+
305988813388 dTLB-loads
|
|
195
|
+
8845723783 dTLB-load-misses # 2.89% of all dTLB cache accesses
|
|
196
|
+
20094264206 cache-misses # 6.567 % of all cache refs
|
|
197
|
+
305988812745 cache-references
|
|
198
|
+
|
|
199
|
+
8.285148010 seconds time elapsed
|
|
200
|
+
|
|
201
|
+
500.705967000 seconds user
|
|
202
|
+
1.371118000 seconds sys
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
If you notice problems and the stalls are closer to 90%, it might be a good reason to consider enabling Huge Pages and tuning allocations alignment.
|
|
206
|
+
To enable Huge Pages:
|
|
207
|
+
|
|
208
|
+
```sh
|
|
209
|
+
sudo cat /proc/sys/vm/nr_hugepages
|
|
210
|
+
sudo sysctl -w vm.nr_hugepages=2048
|
|
211
|
+
sudo reboot
|
|
212
|
+
sudo cat /proc/sys/vm/nr_hugepages
|
|
213
|
+
```
|
|
214
|
+
|
package/docs/c/index.rst
ADDED
package/docs/compilation.md
CHANGED
|
@@ -41,7 +41,10 @@ cmake -B ./build_release \
|
|
|
41
41
|
Linting:
|
|
42
42
|
|
|
43
43
|
```sh
|
|
44
|
-
cppcheck --enable=all --suppress=cstyleCast --suppress=unusedFunction
|
|
44
|
+
cppcheck --enable=all --suppress=cstyleCast --suppress=unusedFunction \
|
|
45
|
+
include/usearch/index.hpp \
|
|
46
|
+
include/index_punned_dense.hpp \
|
|
47
|
+
include/index_punned_helpers.hpp
|
|
45
48
|
```
|
|
46
49
|
|
|
47
50
|
Benchmarking:
|
|
@@ -81,7 +84,7 @@ Benchmarking:
|
|
|
81
84
|
|
|
82
85
|
```sh
|
|
83
86
|
pip install faiss-cpu
|
|
84
|
-
python python/scripts/bench.py \
|
|
87
|
+
python python/scripts/bench.py speed \
|
|
85
88
|
--vectors datasets/wiki_1M/base.1M.fbin \
|
|
86
89
|
--queries datasets/wiki_1M/query.public.100K.fbin \
|
|
87
90
|
--neighbors datasets/wiki_1M/groundtruth.public.100K.ibin
|
|
@@ -92,8 +95,8 @@ python python/scripts/bench.py \
|
|
|
92
95
|
Checking the effect of different embedding dimensions on construction speed:
|
|
93
96
|
|
|
94
97
|
```sh
|
|
95
|
-
python python/scripts/
|
|
96
|
-
python python/scripts/
|
|
98
|
+
python python/scripts/bench.py dimensions ...
|
|
99
|
+
python python/scripts/bench.py connectivity ...
|
|
97
100
|
```
|
|
98
101
|
|
|
99
102
|
## JavaScript
|
|
@@ -114,7 +117,7 @@ cargo publish
|
|
|
114
117
|
|
|
115
118
|
```sh
|
|
116
119
|
gradle clean build
|
|
117
|
-
java -cp . -Djava.library.path
|
|
120
|
+
java -cp . -Djava.library.path="$(pwd)/build/libs/usearch/shared" java/cloud/unum/usearch/Index.java
|
|
118
121
|
```
|
|
119
122
|
|
|
120
123
|
Or step by-step:
|
|
@@ -134,15 +137,14 @@ g++ -shared -o USearchJNI.dll cloud_unum_usearch_Index.o -Wl,--add-stdcall-alias
|
|
|
134
137
|
# MacOS
|
|
135
138
|
g++ -std=c++11 -c -fPIC \
|
|
136
139
|
-I../../../../include \
|
|
137
|
-
-I../../../../src \
|
|
138
140
|
-I../../../../fp16/include \
|
|
139
141
|
-I../../../../robin-map/include \
|
|
140
142
|
-I../../../../simsimd/include \
|
|
141
143
|
-I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
|
|
142
144
|
g++ -dynamiclib -o libusearch.dylib cloud_unum_usearch_Index.o -lc
|
|
143
145
|
# Run linking to that directory
|
|
144
|
-
java -cp . -Djava.library.path
|
|
145
|
-
java -cp . -Djava.library.path
|
|
146
|
+
java -cp . -Djava.library.path="$(pwd)/java/cloud/unum/usearch/" Index.java
|
|
147
|
+
java -cp . -Djava.library.path="$(pwd)/java" cloud.unum.usearch.Index
|
|
146
148
|
```
|
|
147
149
|
|
|
148
150
|
## Wolfram
|
|
@@ -158,6 +160,12 @@ cd golang
|
|
|
158
160
|
go test -v
|
|
159
161
|
```
|
|
160
162
|
|
|
163
|
+
## Objective-C and Swift
|
|
164
|
+
|
|
165
|
+
```sh
|
|
166
|
+
swift build
|
|
167
|
+
```
|
|
168
|
+
|
|
161
169
|
## C
|
|
162
170
|
|
|
163
171
|
### Linux
|
|
@@ -185,4 +193,12 @@ docker buildx create --use &&
|
|
|
185
193
|
--tag unum/usearch:$version \
|
|
186
194
|
--tag unum/usearch:latest \
|
|
187
195
|
--push .
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
Extending metrics in SimSIMD:
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
git push --set-upstream https://github.com/ashvardanian/simsimd.git HEAD:main
|
|
188
204
|
```
|
package/docs/conf.dox
CHANGED
|
@@ -872,7 +872,7 @@ WARN_LOGFILE =
|
|
|
872
872
|
# - Testing
|
|
873
873
|
# - Benchmarks
|
|
874
874
|
|
|
875
|
-
INPUT = ../include/usearch
|
|
875
|
+
INPUT = ../include/usearch ../c/usearch.h ../java/cloud/unum/usearch/Index.java
|
|
876
876
|
|
|
877
877
|
# This tag can be used to specify the character encoding of the source files
|
|
878
878
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
|
@@ -1290,9 +1290,9 @@ HTML_STYLESHEET =
|
|
|
1290
1290
|
# list). For an example see the documentation.
|
|
1291
1291
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
|
1292
1292
|
|
|
1293
|
-
HTML_EXTRA_STYLESHEET =
|
|
1294
|
-
|
|
1295
|
-
|
|
1293
|
+
HTML_EXTRA_STYLESHEET =
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
1296
|
|
|
1297
1297
|
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
|
|
1298
1298
|
# other source files which should be copied to the HTML output directory. Note
|
|
@@ -1302,8 +1302,8 @@ HTML_EXTRA_STYLESHEET = doxygen-awesome-css/doxygen-awesome.css \
|
|
|
1302
1302
|
# files will be copied as-is; there are no commands or markers available.
|
|
1303
1303
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
|
1304
1304
|
|
|
1305
|
-
HTML_EXTRA_FILES =
|
|
1306
|
-
|
|
1305
|
+
HTML_EXTRA_FILES =
|
|
1306
|
+
|
|
1307
1307
|
|
|
1308
1308
|
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
|
1309
1309
|
# will adjust the colors in the style sheet and background images according to
|
package/docs/conf.py
CHANGED
|
@@ -21,7 +21,7 @@ with open('_static/custom.js', 'r+') as js:
|
|
|
21
21
|
|
|
22
22
|
extensions = [
|
|
23
23
|
'breathe', 'm2r2',
|
|
24
|
-
'sphinx.ext.autodoc',
|
|
24
|
+
'sphinx.ext.autodoc', 'sphinx_js',
|
|
25
25
|
'sphinx.ext.autosummary',
|
|
26
26
|
'sphinx.ext.intersphinx',
|
|
27
27
|
'sphinx.ext.napoleon',
|
|
@@ -46,3 +46,5 @@ html_baseurl = '/docs/usearch/'
|
|
|
46
46
|
|
|
47
47
|
breathe_projects = {'USearch': '../build/xml'}
|
|
48
48
|
breathe_default_project = 'USearch'
|
|
49
|
+
|
|
50
|
+
js_source_path = '../javascript/usearch.js'
|
package/docs/index.rst
CHANGED