usearch 2.11.1 → 2.13.1
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/README.md +100 -30
- package/binding.gyp +11 -12
- package/c/README.md +3 -0
- package/c/lib.cpp +50 -13
- package/c/test.c +60 -55
- package/c/usearch.h +16 -0
- package/cpp/CMakeLists.txt +6 -0
- package/cpp/README.md +34 -13
- package/cpp/bench.cpp +99 -47
- package/cpp/test.cpp +947 -132
- package/include/usearch/index.hpp +894 -272
- package/include/usearch/index_dense.hpp +418 -156
- package/include/usearch/index_plugins.hpp +99 -49
- package/javascript/dist/cjs/usearch.d.ts +39 -1
- package/javascript/dist/cjs/usearch.js +11 -1
- package/javascript/dist/esm/usearch.d.ts +39 -1
- package/javascript/dist/esm/usearch.js +11 -1
- package/javascript/tsconfig-esm.json +3 -2
- package/javascript/usearch.ts +18 -7
- package/package.json +2 -2
- package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
- package/prebuilds/linux-arm64/usearch.node +0 -0
- package/prebuilds/linux-x64/usearch.node +0 -0
- package/simsimd/.cmake-format.py +19 -0
- package/simsimd/CONTRIBUTING.md +49 -8
- package/simsimd/Cargo.lock +1 -1
- package/simsimd/Cargo.toml +10 -5
- package/simsimd/Package.swift +16 -0
- package/simsimd/README.md +69 -15
- package/simsimd/binding.gyp +14 -19
- package/simsimd/build.rs +2 -0
- package/simsimd/c/lib.c +18 -0
- package/simsimd/include/module.modulemap +4 -0
- package/simsimd/include/simsimd/binary.h +2 -0
- package/simsimd/include/simsimd/dot.h +466 -32
- package/simsimd/include/simsimd/probability.h +20 -10
- package/simsimd/include/simsimd/simsimd.h +444 -98
- package/simsimd/include/simsimd/spatial.h +480 -44
- package/simsimd/include/simsimd/types.h +161 -39
- package/simsimd/javascript/simsimd.ts +26 -2
- package/simsimd/package.json +1 -1
- package/simsimd/rust/benches/cosine.rs +8 -2
- package/simsimd/rust/benches/native.rs +240 -2
- package/simsimd/rust/benches/sqeuclidean.rs +8 -2
- package/simsimd/rust/lib.rs +50 -13
- package/simsimd/swift/source/SimSIMD.swift +123 -0
- package/simsimd/swift/tests/SimSIMDTests.swift +92 -0
- package/prebuilds/win32-ia32/usearch.node +0 -0
- package/prebuilds/win32-x64/usearch.node +0 -0
- package/simsimd/.releaserc +0 -87
package/simsimd/CONTRIBUTING.md
CHANGED
|
@@ -5,13 +5,34 @@
|
|
|
5
5
|
To rerun experiments utilize the following command:
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
sudo apt install libopenblas-dev # BLAS installation is optional
|
|
9
|
-
cmake -DCMAKE_BUILD_TYPE=Release -DSIMSIMD_BUILD_BENCHMARKS=1 -
|
|
8
|
+
sudo apt install libopenblas-dev # BLAS installation is optional, but recommended for benchmarks
|
|
9
|
+
cmake -DCMAKE_BUILD_TYPE=Release -DSIMSIMD_BUILD_TESTS=1 -DSIMSIMD_BUILD_BENCHMARKS=1 -DSIMSIMD_BUILD_BENCHMARKS_WITH_CBLAS=1 -B build_release
|
|
10
10
|
cmake --build build_release --config Release
|
|
11
11
|
build_release/simsimd_bench
|
|
12
12
|
build_release/simsimd_bench --benchmark_filter=js
|
|
13
13
|
build_release/simsimd_test_run_time
|
|
14
|
-
build_release/simsimd_test_compile_time
|
|
14
|
+
build_release/simsimd_test_compile_time # no need to run this one, it's just a compile-time test
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
To utilize newest instructions, use GCC 12 or newer, or Clang 16 or newer.
|
|
18
|
+
To install them on Ubuntu 22.04, use:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
sudo apt install gcc-12 g++-12
|
|
22
|
+
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100
|
|
23
|
+
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 100
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
On MacOS it's recommended to use Homebrew and install Clang, as opposed to "Apple Clang".
|
|
27
|
+
Replacing the default compiler is not recommended, as it may break the system, but you can pass it as an environment variable:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
brew install llvm
|
|
31
|
+
cmake -DCMAKE_BUILD_TYPE=Release -DSIMSIMD_BUILD_TESTS=1 \
|
|
32
|
+
-DCMAKE_C_COMPILER="$(brew --prefix llvm)/bin/clang" \
|
|
33
|
+
-DCMAKE_CXX_COMPILER="$(brew --prefix llvm)/bin/clang++" \
|
|
34
|
+
-B build_release
|
|
35
|
+
cmake --build build_release --config Release
|
|
15
36
|
```
|
|
16
37
|
|
|
17
38
|
## Python
|
|
@@ -31,11 +52,31 @@ The `-Wd` will silence overflows and runtime warnings.
|
|
|
31
52
|
Benchmarking:
|
|
32
53
|
|
|
33
54
|
```sh
|
|
34
|
-
pip install numpy scipy scikit-learn
|
|
35
|
-
python python/bench.py
|
|
36
|
-
python python/bench.py --n 1000 --ndim
|
|
55
|
+
pip install numpy scipy scikit-learn # for comparison baselines
|
|
56
|
+
python python/bench.py # to run default benchmarks
|
|
57
|
+
python python/bench.py --n 1000 --ndim 1536 # batch size and dimensions
|
|
37
58
|
```
|
|
38
59
|
|
|
60
|
+
You can also benchmark against other libraries:
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
$ python python/bench.py --help
|
|
64
|
+
> usage: bench.py [-h] [--n N] [--ndim NDIM] [--scipy] [--scikit] [--torch] [--tf] [--jax]
|
|
65
|
+
>
|
|
66
|
+
> Benchmark SimSIMD vs. other libraries
|
|
67
|
+
>
|
|
68
|
+
> options:
|
|
69
|
+
> -h, --help show this help message and exit
|
|
70
|
+
> --n N Number of vectors (default: 1000)
|
|
71
|
+
> --ndim NDIM Number of dimensions (default: 1536)
|
|
72
|
+
> --scipy Profile SciPy
|
|
73
|
+
> --scikit Profile scikit-learn
|
|
74
|
+
> --torch Profile PyTorch
|
|
75
|
+
> --tf Profile TensorFlow
|
|
76
|
+
> --jax Profile JAX
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
|
|
39
80
|
Before merging your changes you may want to test your changes against the entire matrix of Python versions USearch supports.
|
|
40
81
|
For that you need the `cibuildwheel`, which is tricky to use on MacOS and Windows, as it would target just the local environment.
|
|
41
82
|
Still, if you have Docker running on any desktop OS, you can use it to build and test the Python bindings for all Python versions for Linux:
|
|
@@ -52,7 +93,7 @@ cibuildwheel --platform macos # works only on MacOS
|
|
|
52
93
|
cibuildwheel --platform windows # works only on Windows
|
|
53
94
|
```
|
|
54
95
|
|
|
55
|
-
You may need root
|
|
96
|
+
You may need root privileges for multi-architecture builds:
|
|
56
97
|
|
|
57
98
|
```sh
|
|
58
99
|
sudo $(which cibuildwheel) --platform linux
|
|
@@ -70,7 +111,7 @@ python -m cibuildwheel --platform windows
|
|
|
70
111
|
cargo test -p simsimd
|
|
71
112
|
cargo test -p simsimd -- --nocapture # To see the output
|
|
72
113
|
cargo bench
|
|
73
|
-
open
|
|
114
|
+
open target/criterion/report/index.html
|
|
74
115
|
```
|
|
75
116
|
|
|
76
117
|
## JavaScript
|
package/simsimd/Cargo.lock
CHANGED
package/simsimd/Cargo.toml
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "simsimd"
|
|
3
3
|
description = "Fastest SIMD-Accelerated Vector Similarity Functions for x86 and Arm"
|
|
4
|
-
version = "
|
|
4
|
+
version = "5.0.0"
|
|
5
5
|
edition = "2021"
|
|
6
6
|
license = "Apache-2.0"
|
|
7
|
-
authors = [
|
|
8
|
-
"Ash Vardanian <1983160+ashvardanian@users.noreply.github.com>",
|
|
9
|
-
"Pedro Planel <pplanel@gmail.com>",
|
|
10
|
-
]
|
|
7
|
+
authors = ["Ash Vardanian <1983160+ashvardanian@users.noreply.github.com>"]
|
|
11
8
|
repository = "https://github.com/ashvardanian/SimSIMD"
|
|
12
9
|
documentation = "https://docs.rs/simsimd"
|
|
13
10
|
homepage = "https://ashvardanian.com/posts/simsimd-faster-scipy"
|
|
@@ -19,6 +16,8 @@ categories = [
|
|
|
19
16
|
"wasm",
|
|
20
17
|
"external-ffi-bindings",
|
|
21
18
|
]
|
|
19
|
+
include = ["/rust/**", "/c/**", "/include/**", "/build.rs"]
|
|
20
|
+
|
|
22
21
|
|
|
23
22
|
[lib]
|
|
24
23
|
name = "simsimd"
|
|
@@ -38,6 +37,12 @@ name = "sqeuclidean"
|
|
|
38
37
|
harness = false
|
|
39
38
|
path = "rust/benches/sqeuclidean.rs"
|
|
40
39
|
|
|
40
|
+
[profile.bench]
|
|
41
|
+
opt-level = 3 # Corresponds to -O3
|
|
42
|
+
lto = true # Enables Link Time Optimization for further optimizations
|
|
43
|
+
codegen-units = 1 # May increase compilation time but optimizes further
|
|
44
|
+
rpath = false # On some systems, setting this to false can help with optimizations
|
|
45
|
+
|
|
41
46
|
[dev-dependencies]
|
|
42
47
|
criterion = { version = "0.5.1" }
|
|
43
48
|
rand = { version = "0.8.5" }
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// swift-tools-version:5.0
|
|
2
|
+
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
|
3
|
+
|
|
4
|
+
import PackageDescription
|
|
5
|
+
|
|
6
|
+
let package = Package(
|
|
7
|
+
name: "SimSIMD",
|
|
8
|
+
products: [
|
|
9
|
+
.library(name: "SimSIMD", targets: ["SimSIMD"]),
|
|
10
|
+
],
|
|
11
|
+
targets: [
|
|
12
|
+
.testTarget(name: "SimSIMDTests", dependencies: ["SimSIMD"], path: "swift/tests"),
|
|
13
|
+
.target(name: "SimSIMD", dependencies: ["CSimSIMD"], path: "swift/source"),
|
|
14
|
+
.systemLibrary(name: "CSimSIMD", path: "include")
|
|
15
|
+
]
|
|
16
|
+
)
|
package/simsimd/README.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# SimSIMD 📏
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Computing dot-products, similarity measures, and distances between low- and high-dimensional vectors is ubiquitous in Machine Learning, Scientific Computing, Geo-Spatial Analysis, and Information Retrieval.
|
|
4
6
|
These algorithms generally have linear complexity in time, constant complexity in space, and are data-parallel.
|
|
5
7
|
In other words, it is easily parallelizable and vectorizable and often available in packages like BLAS and LAPACK, as well as higher-level `numpy` and `scipy` Python libraries.
|
|
6
8
|
Ironically, even with decades of evolution in compilers and numerical computing, [most libraries can be 3-200x slower than hardware potential][benchmarks] even on the most popular hardware, like 64-bit x86 and Arm CPUs.
|
|
7
9
|
SimSIMD attempts to fill that gap.
|
|
8
10
|
1️⃣ SimSIMD functions are practically as fast as `memcpy`.
|
|
9
|
-
2️⃣ SimSIMD [compiles to more platforms than NumPy (105 vs 35)][compatibility] and has more backends than most BLAS implementations.
|
|
11
|
+
2️⃣ SimSIMD [compiles to more platforms than NumPy (105 vs 35)][compatibility] and has more backends than most BLAS implementations.
|
|
10
12
|
|
|
11
13
|
[benchmarks]: https://ashvardanian.com/posts/simsimd-faster-scipy
|
|
12
14
|
[compatibility]: https://pypi.org/project/simsimd/#files
|
|
@@ -64,8 +66,8 @@ Moreover, SimSIMD...
|
|
|
64
66
|
|
|
65
67
|
Due to the high-level of fragmentation of SIMD support in different x86 CPUs, SimSIMD uses the names of select Intel CPU generations for its backends.
|
|
66
68
|
They, however, also work on AMD CPUs.
|
|
67
|
-
|
|
68
|
-
You can learn more about the technical implementation details in the following
|
|
69
|
+
Intel Haswell is compatible with AMD Zen 1/2/3, while AMD Genoa Zen 4 covers AVX-512 instructions added to Intel Skylake and Ice Lake.
|
|
70
|
+
You can learn more about the technical implementation details in the following blog-posts:
|
|
69
71
|
|
|
70
72
|
- [Uses Horner's method for polynomial approximations, beating GCC 12 by 119x](https://ashvardanian.com/posts/gcc-12-vs-avx512fp16/).
|
|
71
73
|
- [Uses Arm SVE and x86 AVX-512's masked loads to eliminate tail `for`-loops](https://ashvardanian.com/posts/simsimd-faster-scipy/#tails-of-the-past-the-significance-of-masked-loads).
|
|
@@ -377,18 +379,49 @@ fn main() {
|
|
|
377
379
|
}
|
|
378
380
|
```
|
|
379
381
|
|
|
382
|
+
### Half-Precision Brain-Float Numbers
|
|
383
|
+
|
|
384
|
+
The "brain-float-16" is a popular machine learning format.
|
|
385
|
+
It's broadly supported in hardware and is very machine-friendly, but software support is still lagging behind.
|
|
386
|
+
[Unlike NumPy](https://github.com/numpy/numpy/issues/19808), you can already use `bf16` datatype in SimSIMD.
|
|
387
|
+
Luckily, to downcast `f32` to `bf16` you only have to drop the last 16 bits:
|
|
388
|
+
|
|
389
|
+
```py
|
|
390
|
+
import numpy as np
|
|
391
|
+
import simsimd as simd
|
|
392
|
+
|
|
393
|
+
a = np.random.randn(ndim).astype(np.float32)
|
|
394
|
+
b = np.random.randn(ndim).astype(np.float32)
|
|
395
|
+
|
|
396
|
+
# NumPy doesn't natively support brain-float, so we need a trick!
|
|
397
|
+
# Luckily, it's very easy to reduce the representation accuracy
|
|
398
|
+
# by simply masking the low 16-bits of our 32-bit single-precision
|
|
399
|
+
# numbers. We can also add `0x8000` to round the numbers.
|
|
400
|
+
a_f32rounded = ((a.view(np.uint32) + 0x8000) & 0xFFFF0000).view(np.float32)
|
|
401
|
+
b_f32rounded = ((b.view(np.uint32) + 0x8000) & 0xFFFF0000).view(np.float32)
|
|
402
|
+
|
|
403
|
+
# To represent them as brain-floats, we need to drop the second half
|
|
404
|
+
a_bf16 = np.right_shift(a_f32rounded.view(np.uint32), 16).astype(np.uint16)
|
|
405
|
+
b_bf16 = np.right_shift(b_f32rounded.view(np.uint32), 16).astype(np.uint16)
|
|
406
|
+
|
|
407
|
+
# Now we can compare the results
|
|
408
|
+
expected = np.inner(a_f32rounded, b_f32rounded)
|
|
409
|
+
result = simd.inner(a_bf16, b_bf16, "bf16")
|
|
410
|
+
```
|
|
411
|
+
|
|
380
412
|
### Dynamic Dispatch
|
|
381
413
|
|
|
382
414
|
SimSIMD provides a dynamic dispatch mechanism to select the most advanced micro-kernel for the current CPU.
|
|
383
415
|
You can query supported backends and use the `SimSIMD::capabilities` function to select the best one.
|
|
384
416
|
|
|
385
417
|
```rust
|
|
386
|
-
println!("uses neon: {}",
|
|
387
|
-
println!("uses sve: {}",
|
|
388
|
-
println!("uses haswell: {}",
|
|
389
|
-
println!("uses skylake: {}",
|
|
390
|
-
println!("uses ice: {}",
|
|
391
|
-
println!("uses
|
|
418
|
+
println!("uses neon: {}", capabilities::uses_neon());
|
|
419
|
+
println!("uses sve: {}", capabilities::uses_sve());
|
|
420
|
+
println!("uses haswell: {}", capabilities::uses_haswell());
|
|
421
|
+
println!("uses skylake: {}", capabilities::uses_skylake());
|
|
422
|
+
println!("uses ice: {}", capabilities::uses_ice());
|
|
423
|
+
println!("uses genoa: {}", capabilities::uses_genoa());
|
|
424
|
+
println!("uses sapphire: {}", capabilities::uses_sapphire());
|
|
392
425
|
```
|
|
393
426
|
|
|
394
427
|
## Using SimSIMD in JavaScript
|
|
@@ -400,8 +433,7 @@ To install, choose one of the following options depending on your environment:
|
|
|
400
433
|
- `pnpm add simsimd`
|
|
401
434
|
- `bun install simsimd`
|
|
402
435
|
|
|
403
|
-
The package is distributed with prebuilt binaries
|
|
404
|
-
If your platform is not supported, you can build the package from the source via `npm run build`.
|
|
436
|
+
The package is distributed with prebuilt binaries, but if your platform is not supported, you can build the package from the source via `npm run build`.
|
|
405
437
|
This will automatically happen unless you install the package with the `--ignore-scripts` flag or use Bun.
|
|
406
438
|
After you install it, you will be able to call the SimSIMD functions on various `TypedArray` variants:
|
|
407
439
|
|
|
@@ -415,14 +447,34 @@ const distance = sqeuclidean(vectorA, vectorB);
|
|
|
415
447
|
console.log('Squared Euclidean Distance:', distance);
|
|
416
448
|
```
|
|
417
449
|
|
|
418
|
-
Other numeric types and precision levels are supported as well
|
|
450
|
+
Other numeric types and precision levels are supported as well.
|
|
451
|
+
For double-precsion floating-point numbers, use `Float64Array`:
|
|
419
452
|
|
|
420
453
|
```js
|
|
421
454
|
const vectorA = new Float64Array([1.0, 2.0, 3.0]);
|
|
422
455
|
const vectorB = new Float64Array([4.0, 5.0, 6.0]);
|
|
423
|
-
|
|
424
456
|
const distance = cosine(vectorA, vectorB);
|
|
425
|
-
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
When doing machine learning and vector search with high-dimensional vectors you may want to quantize them to 8-bit integers.
|
|
460
|
+
You may want to project values from the $[-1, 1]$ range to the $[-100, 100]$ range and then cast them to `Uint8Array`:
|
|
461
|
+
|
|
462
|
+
```js
|
|
463
|
+
const quantizedVectorA = new Uint8Array(vectorA.map(v => (v * 100)));
|
|
464
|
+
const quantizedVectorB = new Uint8Array(vectorB.map(v => (v * 100)));
|
|
465
|
+
const distance = cosine(quantizedVectorA, quantizedVectorB);
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
A more extreme quantization case would be to use binary vectors.
|
|
469
|
+
You can map all positive values to `1` and all negative values and zero to `0`, packing eight values into a single byte.
|
|
470
|
+
After that, Hamming and Jaccard distances can be computed.
|
|
471
|
+
|
|
472
|
+
```js
|
|
473
|
+
const { toBinary, hamming } = require('simsimd');
|
|
474
|
+
|
|
475
|
+
const binaryVectorA = toBinary(vectorA);
|
|
476
|
+
const binaryVectorB = toBinary(vectorB);
|
|
477
|
+
const distance = hamming(binaryVectorA, binaryVectorB);
|
|
426
478
|
```
|
|
427
479
|
|
|
428
480
|
## Using SimSIMD in C
|
|
@@ -469,6 +521,7 @@ int uses_sve = simsimd_uses_sve();
|
|
|
469
521
|
int uses_haswell = simsimd_uses_haswell();
|
|
470
522
|
int uses_skylake = simsimd_uses_skylake();
|
|
471
523
|
int uses_ice = simsimd_uses_ice();
|
|
524
|
+
int uses_genoa = simsimd_uses_genoa();
|
|
472
525
|
int uses_sapphire = simsimd_uses_sapphire();
|
|
473
526
|
|
|
474
527
|
simsimd_capability_t capabilities = simsimd_capabilities();
|
|
@@ -590,6 +643,7 @@ To explicitly disable half-precision support, define the following macro before
|
|
|
590
643
|
|
|
591
644
|
```c
|
|
592
645
|
#define SIMSIMD_NATIVE_F16 0 // or 1
|
|
646
|
+
#define SIMSIMD_NATIVE_BF16 0 // or 1
|
|
593
647
|
#include <simsimd/simsimd.h>
|
|
594
648
|
```
|
|
595
649
|
|
package/simsimd/binding.gyp
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"variables": {
|
|
3
|
-
"openssl_fips": ""
|
|
4
|
-
},
|
|
2
|
+
"variables": {"openssl_fips": ""},
|
|
5
3
|
"targets": [
|
|
6
4
|
{
|
|
7
5
|
"target_name": "simsimd",
|
|
8
6
|
"sources": ["javascript/lib.c"],
|
|
9
7
|
"include_dirs": ["include"],
|
|
10
|
-
"defines": ["SIMSIMD_NATIVE_F16=0"],
|
|
8
|
+
"defines": ["SIMSIMD_NATIVE_F16=0", "SIMSIMD_NATIVE_BF16=0"],
|
|
11
9
|
"cflags": [
|
|
12
10
|
"-std=c11",
|
|
13
11
|
"-ffast-math",
|
|
@@ -17,20 +15,17 @@
|
|
|
17
15
|
"-Wno-switch",
|
|
18
16
|
],
|
|
19
17
|
"conditions": [
|
|
20
|
-
[
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"-arch x86_64"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
}]
|
|
33
|
-
]
|
|
18
|
+
[
|
|
19
|
+
"OS=='mac'",
|
|
20
|
+
{
|
|
21
|
+
"xcode_settings": {
|
|
22
|
+
"MACOSX_DEPLOYMENT_TARGET": "11.0",
|
|
23
|
+
"OTHER_CFLAGS": ["-arch arm64", "-arch x86_64"],
|
|
24
|
+
"OTHER_LDFLAGS": ["-arch arm64", "-arch x86_64"],
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
]
|
|
28
|
+
],
|
|
34
29
|
}
|
|
35
|
-
]
|
|
30
|
+
],
|
|
36
31
|
}
|
package/simsimd/build.rs
CHANGED
|
@@ -5,6 +5,7 @@ fn main() {
|
|
|
5
5
|
.file("c/lib.c")
|
|
6
6
|
.include("include")
|
|
7
7
|
.define("SIMSIMD_NATIVE_F16", "0")
|
|
8
|
+
.define("SIMSIMD_NATIVE_BF16", "0")
|
|
8
9
|
.define("SIMSIMD_DYNAMIC_DISPATCH", "1")
|
|
9
10
|
.flag("-O3")
|
|
10
11
|
.flag("-std=c99") // Enforce C99 standard
|
|
@@ -19,6 +20,7 @@ fn main() {
|
|
|
19
20
|
"arm" | "aarch64" => vec!["SIMSIMD_TARGET_NEON", "SIMSIMD_TARGET_SVE"],
|
|
20
21
|
_ => vec![
|
|
21
22
|
"SIMSIMD_TARGET_SAPPHIRE",
|
|
23
|
+
"SIMSIMD_TARGET_GENOA",
|
|
22
24
|
"SIMSIMD_TARGET_ICE",
|
|
23
25
|
"SIMSIMD_TARGET_SKYLAKE",
|
|
24
26
|
"SIMSIMD_TARGET_HASWELL",
|
package/simsimd/c/lib.c
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
#define SIMSIMD_DYNAMIC_DISPATCH 1
|
|
7
7
|
#define SIMSIMD_NATIVE_F16 0
|
|
8
|
+
#define SIMSIMD_NATIVE_BF16 0
|
|
8
9
|
|
|
9
10
|
/* Depending on the Operating System, the following intrinsics are available
|
|
10
11
|
* on recent compiler toolchains:
|
|
@@ -28,6 +29,9 @@
|
|
|
28
29
|
#if !defined(SIMSIMD_TARGET_ICE) && (defined(_MSC_VER) || defined(__linux__))
|
|
29
30
|
#define SIMSIMD_TARGET_ICE 1
|
|
30
31
|
#endif
|
|
32
|
+
#if !defined(SIMSIMD_TARGET_GENOA) && (defined(__linux__))
|
|
33
|
+
#define SIMSIMD_TARGET_GENOA 1
|
|
34
|
+
#endif
|
|
31
35
|
#if !defined(SIMSIMD_TARGET_SAPPHIRE) && (defined(__linux__))
|
|
32
36
|
#define SIMSIMD_TARGET_SAPPHIRE 1
|
|
33
37
|
#endif
|
|
@@ -67,22 +71,27 @@ simsimd_capability_t simsimd_capabilities(void) {
|
|
|
67
71
|
|
|
68
72
|
// Dot products
|
|
69
73
|
SIMSIMD_METRIC_DECLARATION(dot, f16, f16)
|
|
74
|
+
SIMSIMD_METRIC_DECLARATION(dot, bf16, bf16)
|
|
70
75
|
SIMSIMD_METRIC_DECLARATION(dot, f32, f32)
|
|
71
76
|
SIMSIMD_METRIC_DECLARATION(dot, f64, f64)
|
|
72
77
|
SIMSIMD_METRIC_DECLARATION(dot, f16c, f16)
|
|
78
|
+
SIMSIMD_METRIC_DECLARATION(dot, bf16c, bf16)
|
|
73
79
|
SIMSIMD_METRIC_DECLARATION(dot, f32c, f32)
|
|
74
80
|
SIMSIMD_METRIC_DECLARATION(dot, f64c, f64)
|
|
75
81
|
SIMSIMD_METRIC_DECLARATION(vdot, f16c, f16)
|
|
82
|
+
SIMSIMD_METRIC_DECLARATION(vdot, bf16c, bf16)
|
|
76
83
|
SIMSIMD_METRIC_DECLARATION(vdot, f32c, f32)
|
|
77
84
|
SIMSIMD_METRIC_DECLARATION(vdot, f64c, f64)
|
|
78
85
|
|
|
79
86
|
// Spatial distances
|
|
80
87
|
SIMSIMD_METRIC_DECLARATION(cos, i8, i8)
|
|
81
88
|
SIMSIMD_METRIC_DECLARATION(cos, f16, f16)
|
|
89
|
+
SIMSIMD_METRIC_DECLARATION(cos, bf16, bf16)
|
|
82
90
|
SIMSIMD_METRIC_DECLARATION(cos, f32, f32)
|
|
83
91
|
SIMSIMD_METRIC_DECLARATION(cos, f64, f64)
|
|
84
92
|
SIMSIMD_METRIC_DECLARATION(l2sq, i8, i8)
|
|
85
93
|
SIMSIMD_METRIC_DECLARATION(l2sq, f16, f16)
|
|
94
|
+
SIMSIMD_METRIC_DECLARATION(l2sq, bf16, bf16)
|
|
86
95
|
SIMSIMD_METRIC_DECLARATION(l2sq, f32, f32)
|
|
87
96
|
SIMSIMD_METRIC_DECLARATION(l2sq, f64, f64)
|
|
88
97
|
|
|
@@ -92,17 +101,26 @@ SIMSIMD_METRIC_DECLARATION(jaccard, b8, b8)
|
|
|
92
101
|
|
|
93
102
|
// Probability distributions
|
|
94
103
|
SIMSIMD_METRIC_DECLARATION(kl, f16, f16)
|
|
104
|
+
SIMSIMD_METRIC_DECLARATION(kl, bf16, bf16)
|
|
95
105
|
SIMSIMD_METRIC_DECLARATION(kl, f32, f32)
|
|
96
106
|
SIMSIMD_METRIC_DECLARATION(kl, f64, f64)
|
|
97
107
|
SIMSIMD_METRIC_DECLARATION(js, f16, f16)
|
|
108
|
+
SIMSIMD_METRIC_DECLARATION(js, bf16, bf16)
|
|
98
109
|
SIMSIMD_METRIC_DECLARATION(js, f32, f32)
|
|
99
110
|
SIMSIMD_METRIC_DECLARATION(js, f64, f64)
|
|
100
111
|
|
|
101
112
|
SIMSIMD_DYNAMIC int simsimd_uses_neon(void) { return (simsimd_capabilities() & simsimd_cap_neon_k) != 0; }
|
|
113
|
+
SIMSIMD_DYNAMIC int simsimd_uses_neon_f16(void) { return (simsimd_capabilities() & simsimd_cap_neon_f16_k) != 0; }
|
|
114
|
+
SIMSIMD_DYNAMIC int simsimd_uses_neon_bf16(void) { return (simsimd_capabilities() & simsimd_cap_neon_bf16_k) != 0; }
|
|
115
|
+
SIMSIMD_DYNAMIC int simsimd_uses_neon_i8(void) { return (simsimd_capabilities() & simsimd_cap_neon_i8_k) != 0; }
|
|
102
116
|
SIMSIMD_DYNAMIC int simsimd_uses_sve(void) { return (simsimd_capabilities() & simsimd_cap_sve_k) != 0; }
|
|
117
|
+
SIMSIMD_DYNAMIC int simsimd_uses_sve_f16(void) { return (simsimd_capabilities() & simsimd_cap_sve_f16_k) != 0; }
|
|
118
|
+
SIMSIMD_DYNAMIC int simsimd_uses_sve_bf16(void) { return (simsimd_capabilities() & simsimd_cap_sve_bf16_k) != 0; }
|
|
119
|
+
SIMSIMD_DYNAMIC int simsimd_uses_sve_i8(void) { return (simsimd_capabilities() & simsimd_cap_sve_i8_k) != 0; }
|
|
103
120
|
SIMSIMD_DYNAMIC int simsimd_uses_haswell(void) { return (simsimd_capabilities() & simsimd_cap_haswell_k) != 0; }
|
|
104
121
|
SIMSIMD_DYNAMIC int simsimd_uses_skylake(void) { return (simsimd_capabilities() & simsimd_cap_skylake_k) != 0; }
|
|
105
122
|
SIMSIMD_DYNAMIC int simsimd_uses_ice(void) { return (simsimd_capabilities() & simsimd_cap_ice_k) != 0; }
|
|
123
|
+
SIMSIMD_DYNAMIC int simsimd_uses_genoa(void) { return (simsimd_capabilities() & simsimd_cap_genoa_k) != 0; }
|
|
106
124
|
SIMSIMD_DYNAMIC int simsimd_uses_sapphire(void) { return (simsimd_capabilities() & simsimd_cap_sapphire_k) != 0; }
|
|
107
125
|
|
|
108
126
|
#ifdef __cplusplus
|
|
@@ -78,6 +78,7 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8_serial(simsimd_b8_t const* a, simsimd_b8_
|
|
|
78
78
|
|
|
79
79
|
#if SIMSIMD_TARGET_ARM
|
|
80
80
|
#if SIMSIMD_TARGET_NEON
|
|
81
|
+
#pragma GCC push_options
|
|
81
82
|
#pragma GCC target("+simd")
|
|
82
83
|
#pragma clang attribute push(__attribute__((target("+simd"))), apply_to = function)
|
|
83
84
|
|
|
@@ -117,6 +118,7 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8_neon(simsimd_b8_t const* a, simsimd_b8_t
|
|
|
117
118
|
#endif // SIMSIMD_TARGET_NEON
|
|
118
119
|
|
|
119
120
|
#if SIMSIMD_TARGET_SVE
|
|
121
|
+
#pragma GCC push_options
|
|
120
122
|
#pragma GCC target("+sve")
|
|
121
123
|
#pragma clang attribute push(__attribute__((target("+sve"))), apply_to = function)
|
|
122
124
|
|