usearch 0.2.3 → 0.4.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/ISSUE_TEMPLATE/bug_report.yml +90 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +64 -0
- package/.github/workflows/release.yml +45 -20
- package/.github/workflows/update_version.sh +6 -0
- package/.releaserc +77 -0
- package/.vscode/settings.json +14 -2
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +12 -0
- package/Cargo.toml +1 -1
- package/README.md +246 -220
- package/VERSION +1 -1
- package/binding.gyp +13 -9
- package/build.rs +1 -0
- package/conanfile.py +1 -1
- package/docs/Compilation.md +112 -0
- package/docs/benchmarks.md +182 -0
- package/docs/benchmarks.rst +5 -0
- package/docs/compilation.rst +5 -0
- package/docs/conf.dox +2668 -0
- package/docs/index.rst +7 -0
- package/include/usearch/usearch.hpp +454 -238
- package/javascript/lib.cpp +82 -8
- package/objc/USearchObjective.mm +2 -2
- package/objc/include/USearchObjective.h +10 -9
- package/package.json +7 -1
- package/python/bench.py +37 -7
- package/python/lib.cpp +70 -43
- package/python/test.py +78 -36
- package/rust/lib.cpp +6 -2
- package/simsimd/include/simsimd/simsimd.h +31 -41
- package/src/advanced.hpp +68 -40
- package/src/bench.cpp +24 -23
- package/swift/Index+Sugar.swift +1 -0
- package/swift/Test.swift +1 -0
- package/.github/workflows/package.json +0 -82
- package/CMakeListsInstructions.md +0 -185
package/binding.gyp
CHANGED
|
@@ -15,15 +15,19 @@
|
|
|
15
15
|
"dependencies": [
|
|
16
16
|
"<!(node -p \"require('node-addon-api').gyp\")"
|
|
17
17
|
],
|
|
18
|
-
"cflags
|
|
19
|
-
"cflags_cc
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
"cflags": ["-fexceptions", "-Wunknown-pragmas", "-std=c99"],
|
|
19
|
+
"cflags_cc": ["-fexceptions", "-Wunknown-pragmas", "-std=c++11"],
|
|
20
|
+
"xcode_settings": {
|
|
21
|
+
"GCC_ENABLE_CPP_EXCEPTIONS": "YES",
|
|
22
|
+
"CLANG_CXX_LIBRARY": "libc++",
|
|
23
|
+
"MACOSX_DEPLOYMENT_TARGET": "10.15"
|
|
24
|
+
},
|
|
25
|
+
"msvs_settings": {
|
|
26
|
+
"VCCLCompilerTool": {
|
|
27
|
+
"ExceptionHandling": 1,
|
|
28
|
+
"AdditionalOptions": [ "-std:c++11" ]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
27
31
|
}
|
|
28
32
|
]
|
|
29
33
|
}
|
package/build.rs
CHANGED
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.4.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'
|
|
@@ -0,0 +1,112 @@
|
|
|
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_OPENMP=1 \
|
|
18
|
+
-DUSEARCH_USE_JEMALLOC=1 && \
|
|
19
|
+
make -C ./build_release -j
|
|
20
|
+
|
|
21
|
+
# To benchmark in C++:
|
|
22
|
+
./build_release/bench \
|
|
23
|
+
--vectors datasets/wiki_1M/base.1M.fbin \
|
|
24
|
+
--queries datasets/wiki_1M/query.public.100K.fbin \
|
|
25
|
+
--neighbors datasets/wiki_1M/groundtruth.public.100K.ibin
|
|
26
|
+
|
|
27
|
+
# Large benchmark on a 1TB dataset:
|
|
28
|
+
./build_release/bench \
|
|
29
|
+
--vectors datasets/t2i_1B/base.1B.fbin \
|
|
30
|
+
--queries datasets/t2i_1B/query.public.100K.fbin \
|
|
31
|
+
--neighbors datasets/t2i_1B/groundtruth.public.100K.ibin \
|
|
32
|
+
--output datasets/t2i_1B/index.usearch \
|
|
33
|
+
--cos
|
|
34
|
+
|
|
35
|
+
# To benchmark in Python:
|
|
36
|
+
python python/bench.py \
|
|
37
|
+
--vectors datasets/wiki_1M/base.1M.fbin \
|
|
38
|
+
--queries datasets/wiki_1M/query.public.100K.fbin \
|
|
39
|
+
--neighbors datasets/wiki_1M/groundtruth.public.100K.ibin
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### MacOS
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
brew install libomp llvm
|
|
46
|
+
cmake \
|
|
47
|
+
-DCMAKE_C_COMPILER="/opt/homebrew/opt/llvm/bin/clang" \
|
|
48
|
+
-DCMAKE_CXX_COMPILER="/opt/homebrew/opt/llvm/bin/clang++" \
|
|
49
|
+
-DUSEARCH_USE_SIMD=1 \
|
|
50
|
+
-DUSEARCH_USE_OPENMP=1 \
|
|
51
|
+
-B ./build_release && \
|
|
52
|
+
make -C ./build_release -j
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Python
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
pip install -e .
|
|
59
|
+
pytest python/test.py
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### JavaScript
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
npm install
|
|
66
|
+
node javascript/test.js
|
|
67
|
+
npm publish
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Rust
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
cargo test -p usearch
|
|
74
|
+
cargo publish
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Java
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
gradle clean build
|
|
81
|
+
java -cp . -Djava.library.path=/Users/av/github/usearch/build/libs/usearch/shared java/cloud/unum/usearch/Index.java
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Or step by-step:
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
cs java/unum/cloud/usearch
|
|
88
|
+
javac -h . Index.java
|
|
89
|
+
|
|
90
|
+
# Ubuntu:
|
|
91
|
+
g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
|
|
92
|
+
g++ -shared -fPIC -o libusearch.so cloud_unum_usearch_Index.o -lc
|
|
93
|
+
|
|
94
|
+
# Windows
|
|
95
|
+
g++ -c -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
|
|
96
|
+
g++ -shared -o USearchJNI.dll cloud_unum_usearch_Index.o -Wl,--add-stdcall-alias
|
|
97
|
+
|
|
98
|
+
# MacOS
|
|
99
|
+
g++ -std=c++11 -c -fPIC \
|
|
100
|
+
-I../../../../include -I../../../../src -I../../../../fp16/include -I../../../../simsimd/include \
|
|
101
|
+
-I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
|
|
102
|
+
g++ -dynamiclib -o libusearch.dylib cloud_unum_usearch_Index.o -lc
|
|
103
|
+
# Run linking to that directory
|
|
104
|
+
java -cp . -Djava.library.path=/Users/av/github/usearch/java/cloud/unum/usearch/ Index.java
|
|
105
|
+
java -cp . -Djava.library.path=/Users/av/github/usearch/java cloud.unum.usearch.Index
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Wolfram
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
brew install --cask wolfram-engine
|
|
112
|
+
```
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Benchmarking USearch
|
|
2
|
+
|
|
3
|
+
## Hyper-parameters
|
|
4
|
+
|
|
5
|
+
All major HNSW implementation share an identical list of hyper-parameters:
|
|
6
|
+
|
|
7
|
+
- connectivity (often called `M`),
|
|
8
|
+
- expansion on additions (often called `efConstruction`),
|
|
9
|
+
- expansion on search (often called `ef`).
|
|
10
|
+
|
|
11
|
+
The default values vary drastically.
|
|
12
|
+
|
|
13
|
+
| Library | Connectivity | EF @ A | EF @ S |
|
|
14
|
+
| :-------: | :----------: | :----: | :----: |
|
|
15
|
+
| `hnswlib` | 16 | 200 | 10 |
|
|
16
|
+
| `FAISS` | 32 | 40 | 16 |
|
|
17
|
+
| `USearch` | 16 | 128 | 64 |
|
|
18
|
+
|
|
19
|
+
Below are the performance numbers for a benchmark running on the 64 cores of AWS `c7g.metal` "Graviton 3"-based instances.
|
|
20
|
+
The main columns are:
|
|
21
|
+
|
|
22
|
+
- **Add**: Number of insertion Queries Per Second.
|
|
23
|
+
- **Search**: Number search Queries Per Second.
|
|
24
|
+
- **Recall @1**: How often does approximate search yield the exact best match?
|
|
25
|
+
|
|
26
|
+
### Different "connectivity"
|
|
27
|
+
|
|
28
|
+
| Vectors | Connectivity | EF @ A | EF @ S | **Add**, QPS | **Search**, QPS | **Recall @1** |
|
|
29
|
+
| :--------- | :----------: | :----: | :----: | :----------: | :-------------: | ------------: |
|
|
30
|
+
| `f32` x256 | 16 | 128 | 64 | 75'640 | 131'654 | 99.3% |
|
|
31
|
+
| `f32` x256 | 12 | 128 | 64 | 81'747 | 149'728 | 99.0% |
|
|
32
|
+
| `f32` x256 | 32 | 128 | 64 | 64'368 | 104'050 | 99.4% |
|
|
33
|
+
|
|
34
|
+
### Different "expansion factors"
|
|
35
|
+
|
|
36
|
+
| Vectors | Connectivity | EF @ A | EF @ S | **Add**, QPS | **Search**, QPS | **Recall @1** |
|
|
37
|
+
| :--------- | :----------: | :----: | :----: | :----------: | :-------------: | ------------: |
|
|
38
|
+
| `f32` x256 | 16 | 128 | 64 | 75'640 | 131'654 | 99.3% |
|
|
39
|
+
| `f32` x256 | 16 | 64 | 32 | 128'644 | 228'422 | 97.2% |
|
|
40
|
+
| `f32` x256 | 16 | 256 | 128 | 39'981 | 69'065 | 99.2% |
|
|
41
|
+
|
|
42
|
+
### Different vectors "accuracy"
|
|
43
|
+
|
|
44
|
+
| Vectors | Connectivity | EF @ A | EF @ S | **Add**, QPS | **Search**, QPS | **Recall @1** |
|
|
45
|
+
| :----------- | :----------: | :----: | :----: | :----------: | :-------------: | ------------: |
|
|
46
|
+
| `f32` x256 | 16 | 128 | 64 | 87'995 | 171'856 | 99.1% |
|
|
47
|
+
| `f16` x256 | 16 | 128 | 64 | 87'270 | 153'788 | 98.4% |
|
|
48
|
+
| `f16` x256 ✳️ | 16 | 128 | 64 | 71'454 | 132'673 | 98.4% |
|
|
49
|
+
| `f8` x256 | 16 | 128 | 64 | 115'923 | 274'653 | 98.9% |
|
|
50
|
+
|
|
51
|
+
As seen on the chart, for `f16` accuracy, performance may differ depending on native hardware support for that numeric type.
|
|
52
|
+
Also worth noting, 8-bit quantization results in almost no accuracy loss and may perform better than `f16`.
|
|
53
|
+
|
|
54
|
+
## Utilities
|
|
55
|
+
|
|
56
|
+
Within this repository you will find two commonly used utilities:
|
|
57
|
+
|
|
58
|
+
- `src/bench.cpp` the produces the `bench` binary for broad USearch benchmarks.
|
|
59
|
+
- `python/bench.py` for simple benchmarks against FAISS.
|
|
60
|
+
|
|
61
|
+
To achieve best highest results we suggest compiling locally for the target architecture.
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
cmake -B ./build_release \
|
|
65
|
+
-DCMAKE_BUILD_TYPE=Release \
|
|
66
|
+
-DUSEARCH_USE_OPENMP=1 \
|
|
67
|
+
-DUSEARCH_USE_JEMALLOC=1 && \
|
|
68
|
+
make -C ./build_release -j
|
|
69
|
+
|
|
70
|
+
./build_release/bench --help
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Which would print the following instructions.
|
|
74
|
+
|
|
75
|
+
```txt
|
|
76
|
+
SYNOPSIS
|
|
77
|
+
./build_release/bench [--vectors <path>] [--queries <path>] [--neighbors <path>] [-b] [-j
|
|
78
|
+
<integer>] [-c <integer>] [--expansion-add <integer>]
|
|
79
|
+
[--expansion-search <integer>] [--native|--f16quant|--i8quant]
|
|
80
|
+
[--ip|--l2|--cos|--haversine] [-h]
|
|
81
|
+
|
|
82
|
+
OPTIONS
|
|
83
|
+
--vectors <path>
|
|
84
|
+
.fbin file path to construct the index
|
|
85
|
+
|
|
86
|
+
--queries <path>
|
|
87
|
+
.fbin file path to query the index
|
|
88
|
+
|
|
89
|
+
--neighbors <path>
|
|
90
|
+
.ibin file path with ground truth
|
|
91
|
+
|
|
92
|
+
-b, --big Will switch to uint40_t for neighbors lists with over 4B entries
|
|
93
|
+
-j, --threads <integer>
|
|
94
|
+
Uses all available cores by default
|
|
95
|
+
|
|
96
|
+
-c, --connectivity <integer>
|
|
97
|
+
Index granularity
|
|
98
|
+
|
|
99
|
+
--expansion-add <integer>
|
|
100
|
+
Affects indexing depth
|
|
101
|
+
|
|
102
|
+
--expansion-search <integer>
|
|
103
|
+
Affects search depth
|
|
104
|
+
|
|
105
|
+
--native Use raw templates instead of type-punned classes
|
|
106
|
+
--f16quant Enable `f16_t` quantization
|
|
107
|
+
--i8quant Enable `int8_t` quantization
|
|
108
|
+
--ip Choose Inner Product metric
|
|
109
|
+
--l2 Choose L2 Euclidean metric
|
|
110
|
+
--cos Choose Angular metric
|
|
111
|
+
--haversine Choose Haversine metric
|
|
112
|
+
-h, --help Print this help information on this tool and exit
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Datasets
|
|
116
|
+
|
|
117
|
+
BigANN benchmark is a good starting point, if you are searching for large collections of high-dimensional vectors.
|
|
118
|
+
Those often come with precomputed ground-truth neighbors, which is handy for recall evaluation.
|
|
119
|
+
|
|
120
|
+
| Dataset | Scalar Type | Dimensions | Metric | Size |
|
|
121
|
+
| :-------------------------------------- | :---------: | :--------: | :----: | :-------: |
|
|
122
|
+
| [Unum UForm Wiki][unum-wiki] | float32 | 256 | IP | 1 GB |
|
|
123
|
+
| [Yandex Text-to-Image Sample][unum-t2i] | float32 | 200 | Cos | 1 GB |
|
|
124
|
+
| | | | | |
|
|
125
|
+
| [Microsoft SPACEV][spacev] | int8 | 100 | L2 | 93 GB |
|
|
126
|
+
| [Microsoft Turing-ANNS][turing] | float32 | 100 | L2 | 373 GB |
|
|
127
|
+
| [Yandex Deep1B][deep] | float32 | 96 | L2 | 358 GB |
|
|
128
|
+
| [Yandex Text-to-Image][t2i] | float32 | 200 | Cos | 750 GB |
|
|
129
|
+
| | | | | |
|
|
130
|
+
| [ViT-L/12 LAION][laion] | float32 | 2048 | Cos | 2 - 10 TB |
|
|
131
|
+
|
|
132
|
+
Luckily, smaller samples of those datasets are available.
|
|
133
|
+
|
|
134
|
+
[unum-wiki]: https://huggingface.co/datasets/unum-cloud/ann-wiki-1m
|
|
135
|
+
[unum-t2i]: https://huggingface.co/datasets/unum-cloud/ann-t2i-1m
|
|
136
|
+
[spacev]: https://github.com/microsoft/SPTAG/tree/main/datasets/SPACEV1B
|
|
137
|
+
[turing]: https://learning2hash.github.io/publications/microsoftturinganns1B/
|
|
138
|
+
[t2i]: https://research.yandex.com/blog/benchmarks-for-billion-scale-similarity-search
|
|
139
|
+
[deep]: https://research.yandex.com/blog/benchmarks-for-billion-scale-similarity-search
|
|
140
|
+
[laion]: https://laion.ai/blog/laion-5b/#download-the-data
|
|
141
|
+
|
|
142
|
+
### Unum UForm Wiki
|
|
143
|
+
|
|
144
|
+
```sh
|
|
145
|
+
mkdir -p datasets/wiki_1M/ && \
|
|
146
|
+
wget -nc https://huggingface.co/datasets/unum-cloud/ann-wiki-1m/resolve/main/base.1M.fbin -P datasets/wiki_1M/ &&
|
|
147
|
+
wget -nc https://huggingface.co/datasets/unum-cloud/ann-wiki-1m/resolve/main/query.public.100K.fbin -P datasets/wiki_1M/ &&
|
|
148
|
+
wget -nc https://huggingface.co/datasets/unum-cloud/ann-wiki-1m/resolve/main/groundtruth.public.100K.ibin -P datasets/wiki_1M/
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Yandex Text-to-Image
|
|
152
|
+
|
|
153
|
+
```sh
|
|
154
|
+
mkdir -p datasets/t2i_1B/ && \
|
|
155
|
+
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/T2I/base.1B.fbin -P datasets/t2i_1B/ &&
|
|
156
|
+
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/T2I/base.1M.fbin -P datasets/t2i_1B/ &&
|
|
157
|
+
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/T2I/query.public.100K.fbin -P datasets/t2i_1B/ &&
|
|
158
|
+
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/T2I/groundtruth.public.100K.ibin -P datasets/t2i_1B/
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Yandex Deep1B
|
|
162
|
+
|
|
163
|
+
```sh
|
|
164
|
+
mkdir -p datasets/deep_1B/ && \
|
|
165
|
+
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/base.1B.fbin -P datasets/deep_1B/ &&
|
|
166
|
+
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/base.10M.fbin -P datasets/deep_1B/ &&
|
|
167
|
+
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/query.public.10K.fbin -P datasets/deep_1B/ &&
|
|
168
|
+
wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/groundtruth.public.10K.ibin -P datasets/deep_1B/
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Profiling
|
|
172
|
+
|
|
173
|
+
With `perf`:
|
|
174
|
+
|
|
175
|
+
```sh
|
|
176
|
+
# Pass environment variables with `-E`, and `-d` for details
|
|
177
|
+
sudo -E perf stat -d ./build_release/bench ...
|
|
178
|
+
sudo -E perf mem -d ./build_release/bench ...
|
|
179
|
+
# Sample on-CPU functions for the specified command, at 1 Kilo Hertz:
|
|
180
|
+
sudo -E perf record -F 1000 ./build_release/bench ...
|
|
181
|
+
perf record -d -e arm_spe// -- ./build_release/bench ..
|
|
182
|
+
```
|