Skip to main content

Smaller & Faster Single-File Vector Search Engine from Unum

Project description

USearch

Smaller & Faster Single-File
Vector Search Engine


Discord     LinkedIn     Twitter     Blog     GitHub

Euclidean • Angular • Jaccard • Hamming • Haversine • User-Defined Metrics
C++11PythonJavaScriptJavaRustObjective-CSwiftGoLangWolfram
Linux • MacOS • Windows • Docker • WebAssembly 🔜



FAISS USearch
Implementation 84 K SLOC in faiss/ 1 K SLOC in usearch/
Supported metrics 9 fixed metrics Any User-Defined metrics
Supported ID types uint32_t, uint64_t uint32_t, uint40_t, uint64_t
Dependencies BLAS, OpenMP None
Bindings SWIG Native
Acceleration Learned Quantization Downcasting

FAISS is the industry standard for a high-performance batteries-included vector search engine. Both USearch and FAISS implement the same HNSW algorithm. But they differ in a lot of design decisions. USearch is designed to be compact and broadly compatible without sacrificing performance.

FAISS, f32 USearch, f32 USearch, f16 USearch, f8
Batch Insert 16 K/s 73 K/s 100 K/s 104 K/s
Batch Search 82 K/s 103 K/s 113 K/s 134 K/s
Bulk Insert 76 K/s 105 K/s 115 K/s 202 K/s
Bulk Search 118 K/s 174 K/s 173 K/s 304 K/s
Recall @1 99% 99.2% 99.1% 99.2%

Dataset: 1M vectors sample of the Deep1B dataset. Hardware: c7g.metal AWS instance with 64 cores and DDR5 memory. HNSW was configured with identical hyper-parameters: connectivity M=16, expansion @ construction efConstruction=128, and expansion @ search ef=64. Batch size is 256. Both libraries were compiled for the target architecture. Jump to the Performance Tuning section to read about the effects of those hyper-parameters.

User-Defined Functions

Most vector-search packages focus on just 2 metrics - "Inner Product distance" and "Euclidean distance". That only partially exhausts the list of possible metrics. A good example would be the rare Haversine distance, used to compute the distance between geo-spatial coordinates, extending Vector Search into the GIS domain. Another example would be designing a custom metric for composite embeddings concatenated from multiple AI models in real-world applications. USearch supports that: Python and C++ examples.

USearch: Vector Search Approaches

Unlike older approaches indexing high-dimensional spaces, like KD-Trees and Locality Sensitive Hashing, HNSW doesn't require vectors to be identical in length. They only have to be comparable. So you can apply it in obscure applications, like searching for similar sets or fuzzy text matching.

Memory Efficiency, Downcasting, and Quantization

Training a quantization model and dimension-reduction is a common approach to accelerate vector search. Those, however, are only sometimes reliable, can significantly affect the statistical properties of your data, and require regular adjustments if your distribution shifts.

USearch uint40_t support

Instead, we have focused on high-precision arithmetic over low-precision downcasted vectors. The same index, and add and search operations will automatically down-cast or up-cast between f32_t, f16_t, f64_t, and f8_t representations, even if the hardware doesn't natively support it. Continuing the topic of memory-efficiency, we provide a uint40_t to allow collection with over 4B+ vectors without allocating 8 bytes for every neighbor reference in the proximity graph.

View Larger Indexes from Disk

Modern search systems often suggest using different servers to maximize indexing speed and minimize serving costs. Memory-optimized for the first task, and storage-optimized for the second, if the index can be served from external memory, which USearch can.

To Build To Serve
Instance u-24tb1.metal is4gen.8xlarge
Price ~ $200/h ~$4.5/h
Memory 24 TB RAM + EBS 192 GB RAM + 30 TB SSD

There is a 50x difference between the cost of such instances for identical capacity. Of course, the latency of external memory access will be higher, but it is in part compensated with an excellent prefetching mechanism.

Usage

There are two usage patters:

  1. Bare-bones with usearch/index.hpp, only available in C++.
  2. Full-fat version with it's own threads, mutexes, type-punning, quantization, that is available both in C++ and is wrapped for higher-level bindings.

C++

Installation

To use in a C++ project simply copy the include/usearch/index.hpp header into your project. Alternatively fetch it with CMake:

FetchContent_Declare(usearch GIT_REPOSITORY https://github.com/unum-cloud/usearch.git)
FetchContent_MakeAvailable(usearch)

Quickstart

Once included, the low-level C++11 interface is as simple as it gets: reserve(), add(), search(), size(), capacity(), save(), load(), view(). This covers 90% of use-cases.

using namespace unum::usearch;

index_gt<cos_gt<float>> index;
float vec[3] = {0.1, 0.3, 0.2};

index.reserve(10);
index.add(/* label: */ 42, /* vector: */ {&vec[0], 3});
auto results = index.search(/* query: */ {&vec[0], 3}, 5 /* neighbors */);

for (std::size_t i = 0; i != results.size(); ++i)
    results[i].member.label, results[i].member.vector, results[i].member.id, results[i].distance;

The add is thread-safe for concurrent index construction.

Serialization

index.save("index.usearch");
index.load("index.usearch"); // Copying from disk
index.view("index.usearch"); // Memory-mapping from disk

User-Defined Metrics in C++

For advanced users, more compile-time abstractions are available.

template <typename metric_at = ip_gt<float>,            //
          typename label_at = std::size_t,              // `uint32_t`, `uuid_t`...
          typename id_at = std::uint32_t,               // `uint40_t`, `uint64_t`...
          typename scalar_at = float,                   // `double`, `half`, `char`...
          typename allocator_at = std::allocator<char>> //
class index_gt;

You may want to use a custom memory allocator or a rare scalar type, but most often, you would start by defining a custom similarity measure. The function object should have the following signature to support different-length vectors.

struct custom_metric_t {
    T operator()(T const* a, T const* b, std::size_t a_length, std::size_t b_length) const;
};

The following distances are pre-packaged:

  • cos_gt<scalar_t> for "Cosine" or "Angular" distance.
  • ip_gt<scalar_t> for "Inner Product" or "Dot Product" distance.
  • l2sq_gt<scalar_t> for the squared "L2" or "Euclidean" distance.
  • jaccard_gt<scalar_t> for "Jaccard" distance between two ordered sets of unique elements.
  • hamming_gt<scalar_t> for "Hamming" distance, as the number of shared bits in hashes.
  • tanimoto_gt<scalar_t> for "Tanimoto" coefficient for bit-strings.
  • sorensen_gt<scalar_t> for "Dice-Sorensen" coefficient for bit-strings.
  • pearson_correlation_gt<scalar_t> for "Pearson" correlation between probability distributions.
  • haversine_gt<scalar_t> for "Haversine" or "Great Circle" distance between coordinates used in GIS applications.

Multi-Threading

Most AI, HPC, or Big Data packages use some form of a thread pool. Instead of spawning additional threads within USearch, we focus on the thread safety of add() function, simplifying resource management.

#pragma omp parallel for
    for (std::size_t i = 0; i < n; ++i)
        native.add(label, span_t{vector, dims}, add_config_t { .thread = omp_get_thread_num() });

During initialization, we allocate enough temporary memory for all the cores on the machine. On the call, the user can supply the identifier of the current thread, making this library easy to integrate with OpenMP and similar tools.

Python

Installation

pip install usearch

Quickstart

import numpy as np
from usearch.index import Index

index = Index(
    ndim=3, # Define the number of dimensions in input vectors
    metric='cos', # Choose 'l2sq', 'haversine' or other metric, default = 'ip'
    dtype='f32', # Quantize to 'f16' or 'f8' if needed, default = 'f32'
    connectivity=16, # How frequent should the connections in the graph be, optional
    expansion_add=128, # Control the recall of indexing, optional
    expansion_search=64, # Control the quality of search, optional
)

vector = np.array([0.2, 0.6, 0.4])
index.add(42, vector)
matches, distances, count = index.search(vector, 10)

assert len(index) == 1
assert count == 1
assert matches[0] == 42
assert distances[0] <= 0.001
assert np.allclose(index[42], vector)

Python bindings are implemented with pybind/pybind11. Assuming the presence of Global Interpreter Lock in Python, we spawn threads in the C++ layer on large insertions.

Serialization

index.save('index.usearch')
index.load('index.usearch') # Copy the whole index into memory
index.view('index.usearch') # View from disk without loading in memory

If you don't know anything about the index except its path, there are two more endpoints to know:

Index.metadata('index.usearch') -> IndexMetadata
Index.restore('index.usearch', view=False) -> Index

Batch Operations

Adding or querying a batch of entries is identical to adding a single vector. The difference would be in the shape of the tensors.

n = 100
labels = np.arange(n)
vectors = np.random.uniform(0, 0.3, (n, index.ndim)).astype(np.float32)

index.add(labels, vectors, threads=..., copy=...)
matches, distances, counts = index.search(vectors, 10, threads=...)

assert matches.shape[0] == vectors.shape[0]
assert counts[0] <= 10

You can also override the default threads and copy arguments in bulk workloads. The first controls the number of threads spawned for the task. The second controls whether the vector itself will be persisted inside the index. If you can preserve the lifetime of the vector somewhere else, you can avoid the copy.

User-Defined Metrics and JIT in Python

Numba

Assuming the language boundary exists between Python user code and C++ implementation, there are more efficient solutions than passing a Python callable to the engine. Luckily, with the help of Numba, we can JIT compile a function with a matching signature and pass it down to the engine.

from numba import cfunc, types, carray

ndim = 256
signature = types.float32(
    types.CPointer(types.float32),
    types.CPointer(types.float32))

@cfunc(signature)
def inner_product(a, b):
    a_array = carray(a, ndim)
    b_array = carray(b, ndim)
    c = 0.0
    for i in range(ndim):
        c += a_array[i] * b_array[i]
    return 1 - c

index = Index(ndim=ndim, metric=CompiledMetric(
    pointer=inner_product.address,
    kind=MetricKind.IP,
    signature=MetricSignature.ArrayArray,
))

Alternatively, you can avoid pre-defining the number of dimensions, and pass it separately:

signature = types.float32(
    types.CPointer(types.float32),
    types.CPointer(types.float32),
    types.uint64)

@cfunc(signature)
def inner_product(a, b, ndim):
    a_array = carray(a, ndim)
    b_array = carray(b, ndim)
    c = 0.0
    for i in range(ndim):
        c += a_array[i] * b_array[i]
    return 1 - c

index = Index(ndim=ndim, metric=CompiledMetric(
    pointer=inner_product.address,
    kind=MetricKind.IP,
    signature=MetricSignature.ArrayArraySize,
))
pip install numba
Cppyy

Similarly, you can use Cppyy with Cling to JIT-compile native C or C++ code and pass it to USearch, which may be a good idea, if you want to explicitly request loop-unrolling or other low-level optimizations!

import cppyy
import cppyy.ll

cppyy.cppdef("""
float inner_product(float *a, float *b) {
    float result = 0;
#pragma unroll
    for (size_t i = 0; i != ndim; ++i)
        result += a[i] * b[i];
    return 1 - result;
}
""".replace("ndim", str(ndim)))

function = cppyy.gbl.inner_product
index = Index(ndim=ndim, metric=CompiledMetric(
    pointer=cppyy.ll.addressof(function),
    kind=MetricKind.IP,
    signature=MetricSignature.ArrayArraySize,
))
conda install -c conda-forge cppyy
PeachPy

We have covered JIT-ing Python with Numba and C++ with Cppyy and Cling. How about writing Assembly directly? That is also possible. Below is an example of constructing the "Inner Product" distance for 8-dimensional f32 vectors for x86 using PeachPy.

from peachpy import (
    Argument,
    ptr,
    float_,
    const_float_,
)
from peachpy.x86_64 import (
    abi,
    Function,
    uarch,
    isa,
    GeneralPurposeRegister64,
    LOAD,
    YMMRegister,
    VSUBPS,
    VADDPS,
    VHADDPS,
    VMOVUPS,
    VFMADD231PS,
    VPERM2F128,
    VXORPS,
    RETURN,
)

a = Argument(ptr(const_float_), name="a")
b = Argument(ptr(const_float_), name="b")

with Function(
    "inner_product", (a, b), float_, target=uarch.default + isa.avx2
) as asm_function:
    
    # Request two 64-bit general-purpose registers for addresses
    reg_a, reg_b = GeneralPurposeRegister64(), GeneralPurposeRegister64()
    LOAD.ARGUMENT(reg_a, a)
    LOAD.ARGUMENT(reg_b, b)

    # Load the vectors
    ymm_a = YMMRegister()
    ymm_b = YMMRegister()
    VMOVUPS(ymm_a, [reg_a])
    VMOVUPS(ymm_b, [reg_b])

    # Prepare the accumulator
    ymm_c = YMMRegister()
    ymm_one = YMMRegister()
    VXORPS(ymm_c, ymm_c, ymm_c)
    VXORPS(ymm_one, ymm_one, ymm_one)

    # Accumulate A and B product into C
    VFMADD231PS(ymm_c, ymm_a, ymm_b)

    # Reduce the contents of a YMM register
    ymm_c_permuted = YMMRegister()
    VPERM2F128(ymm_c_permuted, ymm_c, ymm_c, 1)
    VADDPS(ymm_c, ymm_c, ymm_c_permuted)
    VHADDPS(ymm_c, ymm_c, ymm_c)
    VHADDPS(ymm_c, ymm_c, ymm_c)

    # Negate the values, to go from "similarity" to "distance"
    VSUBPS(ymm_c, ymm_one, ymm_c)

    # A common convention is to return floats in XMM registers
    RETURN(ymm_c.as_xmm)

python_function = asm_function.finalize(abi.detect()).encode().load()
metric = CompiledMetric(
    pointer=python_function.loader.code_address,
    kind=MetricKind.IP,
    signature=MetricSignature.ArrayArray,
)
index = Index(ndim=ndim, metric=metric)

Tooling

To work with bbin, fbin, ibin, hbin matrix files USearch provides load_matrix and save_matrix. Such files are standard in k-ANN tasks and represent a binary object with all the scalars, prepended by two 32-bit integers - the number of rows and columns in the matrix.

from usearch.index import Index
from usearch.io import load_matrix, save_matrix

vectors = load_matrix('deep1B.fbin')
index = Index(ndim=vectors.shape[1])
index.add(labels, vectors)

One may often want to evaluate the quality of the constructed index before running in production. The trivial way is to measure recall@1 on the entries already present in the index.

from usearch.eval import recall_members

assert recall_members(index, exact=True) == 1
print(recall_members(index, exact=False))

In case you have some ground-truth data for more than one entry, you compare search results against expected values:

from usearch.eval import relevance, dcg, ndcg, random_vectors

vectors = random_vectors(index=index)
matches_approximate = index.search(vectors)
matches_exact = index.search(vectors, exact=True)
relevance_scores = relevance(matches_exact, matches_approximate)
print(dcg(relevance_scores), ndcg(relevance_scores))

JavaScript

Installation

npm install usearch

Quickstart

var index = new usearch.Index({ metric: 'cos', connectivity: 16, dimensions: 3 })
index.add(42, new Float32Array([0.2, 0.6, 0.4]))
var results = index.search(new Float32Array([0.2, 0.6, 0.4]), 10)

assert.equal(index.size(), 1)
assert.deepEqual(results.labels, new Uint32Array([42]))
assert.deepEqual(results.distances, new Float32Array([0]))

Serialization

index.save('index.usearch')
index.load('index.usearch')
index.view('index.usearch')

Rust

Installation

cargo add usearch

Quickstart

let options = IndexOptions {
            dimensions: 5,
            metric: MetricKind::IP,
            quantization: ScalarKind::F16,
            connectivity: 0,
            expansion_add: 0,
            expansion_search: 0
        };

let index = new_index(&options).unwrap();

assert!(index.reserve(10).is_ok());
assert!(index.capacity() >= 10);
assert!(index.connectivity() != 0);
assert_eq!(index.dimensions(), 3);
assert_eq!(index.size(), 0);

let first: [f32; 3] = [0.2, 0.1, 0.2];
let second: [f32; 3] = [0.2, 0.1, 0.2];

assert!(index.add(42, &first).is_ok());
assert!(index.add(43, &second).is_ok());
assert_eq!(index.size(), 2);

// Read back the tags
let results = index.search(&first, 10).unwrap();
assert_eq!(results.count, 2);

Multi-Threading

assert!(index.add_in_thread(42, &first, 0).is_ok());
assert!(index.add_in_thread(43, &second, 0).is_ok());
let results = index.search_in_thread(&first, 10, 0).unwrap();

Being a systems-programming language, Rust has better control over memory management and concurrency but lacks function overloading. Aside from the add and search, USearch Rust binding also provides add_in_thread and search_in_thread, which let users identify the calling thread to use underlying temporary memory more efficiently.

Serialization

assert!(index.save("index.usearch").is_ok());
assert!(index.load("index.usearch").is_ok());
assert!(index.view("index.usearch").is_ok());

Metrics

assert!(new_l2sq(3, &quant, 0, 0, 0).is_ok());
assert!(new_cos(3, &quant, 0, 0, 0).is_ok());
assert!(new_haversine(&quant, 0, 0, 0).is_ok());

Java

Installation

<dependency>
  <groupId>cloud.unum</groupId>
  <artifactId>usearch</artifactId>
  <version>0.2.3</version>
</dependency>

Add that snippet to your pom.xml and hit mvn install.

Quickstart

Index index = new Index.Config().metric("cos").dimensions(2).build();
float vec[] = {10, 20};
index.add(42, vec);
int[] labels = index.search(vec, 5);

Swift

Installation

https://github.com/unum-cloud/usearch

Quickstart

let index = Index.l2sq(dimensions: 3, connectivity: 8)
let vectorA: [Float32] = [0.3, 0.5, 1.2]
let vectorB: [Float32] = [0.4, 0.2, 1.2]
index.reserve(2)
index.add(label: 42, vector: vectorA[...])
index.add(label: 43, vector: vectorB[...])

let results = index.search(vector: vectorA[...], count: 10)
assert(results.0[0] == 42)

GoLang

Installation

import (
	"github.com/unum-cloud/usearch/golang"
)

Quickstart

package main

import (
	"fmt"
	"github.com/unum-cloud/usearch/golang"
)

func main() {
	conf := usearch.DefaultConfig(128)
	index := usearch.NewIndex(conf)
	v := make([]float32, 128)
	index.Add(42, v)
	results := index.Search(v, 1)
}

Wolfram

Application Examples

USearch + AI = Multi-Modal Semantic Search

AI has a growing number of applications, but one of the coolest classic ideas is to use it for Semantic Search. One can take an encoder model, like the multi-modal UForm, and a web-programming framework, like UCall, and build a text-to-image search platform in just 20 lines of Python.

import ucall
import uform
import usearch

import numpy as np
import PIL as pil

server = ucall.Server()
model = uform.get_model('unum-cloud/uform-vl-multilingual')
index = usearch.index.Index(ndim=256)

@server
def add(label: int, photo: pil.Image.Image):
    image = model.preprocess_image(photo)
    vector = model.encode_image(image).detach().numpy()
    index.add(label, vector.flatten(), copy=True)

@server
def search(query: str) -> np.ndarray:
    tokens = model.preprocess_text(query)
    vector = model.encode_text(tokens).detach().numpy()
    matches = index.search(vector.flatten(), 3)
    return matches.labels

server.run()

We have pre-processed some commonly used datasets, cleaning the images, producing the vectors, and pre-building the index.

Dataset Size Images Preprocessed
Unsplash 25K - 25 K HF
Createve Captions 3M - 3 M HF

USearch + RDKit = Molecular Search

Comparing molecule graphs and searching for similar structures is expensive and slow. It can be seen as a special case of the NP-Complete Subgraph Isomorphism problem. Luckily, domain-specific approximate methods exists. The one commonly used in Chemistry, is to generate structures from SMILES, and later hash them into binary fingerprints. The later are searchable with bitwise similarity metrics, like the Tanimoto coefficient. Below is na example using the RDKit package.

from usearch.index import Index, MetricKind
from rdkit import Chem
from rdkit.Chem import AllChem

import numpy as np

molecules = [Chem.MolFromSmiles('CCOC'), Chem.MolFromSmiles('CCO')]
encoder = AllChem.GetRDKitFPGenerator()

fingerprints = np.vstack([encoder.GetFingerprint(x) for x in molecules])
fingerprints = np.packbits(fingerprints, axis=1)

index = Index(ndim=2048, metric=MetricKind.BitwiseTanimoto)
labels = np.arange(len(molecules))

index.add(labels, fingerprints)
matches: Matches = index.search(fingerprints, 10)

Of if you need a bit of our SIMD superpowers - take some Chemsitry-oriented precompiled metrics from SimSIMD.

import simsimd as sisi

index = Index(
    ndim=166, # MACCS fingerprints are 166-dimensional
    metric=CompiledMetric(
        pointer=sisi.to_int(sisi.tanimoto_maccs_neon), # For Arm Neon
        signature=MetricSignature.ArrayArray,
        kind=MetricKind.Tanimoto,
    ),
)

index.add(42, np.packbits([1] * 166))
matches: Matches = index.search(np.packbits([1] * 166))

TODO

  • JavaScript: Allow calling from "worker threads".
  • Rust: Allow passing a custom thread ID.
  • C# .NET bindings.

Integrations

  • GPT-Cache.
  • Langchain.
  • Microsoft Semantic Kernel.
  • PyTorch.

Citations

@software{Vardanian_USearch_2022,
doi = {10.5281/zenodo.7949416},
author = {Vardanian, Ash},
title = {{USearch by Unum Cloud}},
url = {https://github.com/unum-cloud/usearch},
version = {0.13.0},
year = {2022}
month = jun,
}

Check that and other examples on our corporate GitHub 🤗

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

usearch-0.21.0-cp311-cp311-win_amd64.whl (191.2 kB view details)

Uploaded CPython 3.11 Windows x86-64

usearch-0.21.0-cp311-cp311-manylinux_2_28_x86_64.whl (352.9 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.28+ x86-64

usearch-0.21.0-cp311-cp311-manylinux_2_28_aarch64.whl (339.6 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.28+ ARM64

usearch-0.21.0-cp311-cp311-macosx_11_0_arm64.whl (245.3 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

usearch-0.21.0-cp311-cp311-macosx_10_9_x86_64.whl (254.5 kB view details)

Uploaded CPython 3.11 macOS 10.9+ x86-64

usearch-0.21.0-cp311-cp311-macosx_10_9_universal2.whl (470.8 kB view details)

Uploaded CPython 3.11 macOS 10.9+ universal2 (ARM64, x86-64)

usearch-0.21.0-cp310-cp310-win_amd64.whl (190.0 kB view details)

Uploaded CPython 3.10 Windows x86-64

usearch-0.21.0-cp310-cp310-manylinux_2_28_x86_64.whl (351.8 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.28+ x86-64

usearch-0.21.0-cp310-cp310-manylinux_2_28_aarch64.whl (338.8 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.28+ ARM64

usearch-0.21.0-cp310-cp310-macosx_11_0_arm64.whl (243.6 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

usearch-0.21.0-cp310-cp310-macosx_10_9_x86_64.whl (253.4 kB view details)

Uploaded CPython 3.10 macOS 10.9+ x86-64

usearch-0.21.0-cp310-cp310-macosx_10_9_universal2.whl (469.2 kB view details)

Uploaded CPython 3.10 macOS 10.9+ universal2 (ARM64, x86-64)

usearch-0.21.0-cp39-cp39-win_amd64.whl (190.1 kB view details)

Uploaded CPython 3.9 Windows x86-64

usearch-0.21.0-cp39-cp39-manylinux_2_28_x86_64.whl (351.8 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.28+ x86-64

usearch-0.21.0-cp39-cp39-manylinux_2_28_aarch64.whl (338.8 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.28+ ARM64

usearch-0.21.0-cp39-cp39-macosx_11_0_arm64.whl (243.9 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

usearch-0.21.0-cp39-cp39-macosx_10_9_x86_64.whl (253.5 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

usearch-0.21.0-cp39-cp39-macosx_10_9_universal2.whl (469.3 kB view details)

Uploaded CPython 3.9 macOS 10.9+ universal2 (ARM64, x86-64)

usearch-0.21.0-cp38-cp38-win_amd64.whl (189.9 kB view details)

Uploaded CPython 3.8 Windows x86-64

usearch-0.21.0-cp38-cp38-manylinux_2_28_x86_64.whl (351.4 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.28+ x86-64

usearch-0.21.0-cp38-cp38-manylinux_2_28_aarch64.whl (338.6 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.28+ ARM64

usearch-0.21.0-cp38-cp38-macosx_11_0_arm64.whl (243.5 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

usearch-0.21.0-cp38-cp38-macosx_10_9_x86_64.whl (253.3 kB view details)

Uploaded CPython 3.8 macOS 10.9+ x86-64

usearch-0.21.0-cp38-cp38-macosx_10_9_universal2.whl (468.9 kB view details)

Uploaded CPython 3.8 macOS 10.9+ universal2 (ARM64, x86-64)

usearch-0.21.0-cp37-cp37m-win_amd64.whl (190.3 kB view details)

Uploaded CPython 3.7m Windows x86-64

usearch-0.21.0-cp37-cp37m-manylinux_2_28_x86_64.whl (356.1 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.28+ x86-64

usearch-0.21.0-cp37-cp37m-manylinux_2_28_aarch64.whl (344.3 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.28+ ARM64

usearch-0.21.0-cp37-cp37m-macosx_10_9_x86_64.whl (250.4 kB view details)

Uploaded CPython 3.7m macOS 10.9+ x86-64

File details

Details for the file usearch-0.21.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: usearch-0.21.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 191.2 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/4.0.2 CPython/3.11.4

File hashes

Hashes for usearch-0.21.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 d5f963b0f58fedd8952ca10734bcde51efc98a507ef6ccc6679117922a0501b0
MD5 77af7ca7f8b947f54c06e5114ebe0421
BLAKE2b-256 cbc341ad0696ca61e3c10a1428911c072520a1bead0dcca24cc777e5078440d2

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 edcaba4d509b3758542a03f961f6779911fec1d05a874864dad8acd4805632f0
MD5 a003b6d7e12e55c24f0188c7eaf87818
BLAKE2b-256 6abf8c7bef2c37cce45417c884dcb88a0fca5e09e935ca8fc8b3751f355cc8b0

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp311-cp311-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp311-cp311-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 8544ec038bc7d9ba52acf0086fd4218238e1132f823b6b0291db7ddf1fe324d6
MD5 333fc1f82854f18f6b140b7201b94c09
BLAKE2b-256 bc4499db10353e8e5745ca99452df91b6d8a97515315f2f038c3f2b9ecbbaea0

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2e1549cba44ea01a1122fd68b672a0e8db379a3f22209502753e5300d6073997
MD5 e30a24d1c60de97c22f1e8a0c56326a3
BLAKE2b-256 c2542766e0862b5f544bf6879af6aaf23c3de4754f90b42bc0203e0af4ce1fdf

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 192a3f01e61097b56aec24369033c241e2060cc4c0fbb26e285306102fafb8eb
MD5 2120894d9856fc8e53fd31ec7ad06f65
BLAKE2b-256 a6f4079935ef9942c10267e569957ae4c5d8436d7cec5d0d9bd51dc70ad3088e

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp311-cp311-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp311-cp311-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 eebecad0b8fc47d72fd94f69e75498ad616650c432021e4b479c607892b41146
MD5 2a0ac4ca273d4a2502a503aa60e40708
BLAKE2b-256 a9671ddcd86fce9eee96e1b0b5e7baf3a88824779eb46490652975e4ff0e75eb

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: usearch-0.21.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 190.0 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/4.0.2 CPython/3.11.4

File hashes

Hashes for usearch-0.21.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 11ced223419748253242218bd9b9c3d4882df9ea82f9702a0c91fdb4bfc29edd
MD5 f2e83195277e6fd77119a14a9bae1415
BLAKE2b-256 da2b369f7d03f616a8aa651c33aa1b47768bd777519348aadf2ab668c9ba012d

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp310-cp310-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp310-cp310-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 3abcbb32c821869f52c4ec846162b3758430a94285d3a7869808ea02afee3e48
MD5 de17106df2eb30001a9acbc625004ca6
BLAKE2b-256 d5fe0694aab4bf4a4b5a148ab5a526d0cc16aa0a6146907a3bf4a8a5f8593b4c

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp310-cp310-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp310-cp310-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 89c420c9ef4e541de41103ca8db4f399e7f9128fe6f0da40845695e2ca433ea3
MD5 9b58211d90126cd412055a5957028548
BLAKE2b-256 ef83eda284dd9c7cd387fece10552d9aa58a714f4233e070f4bba6a41976c782

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9c49fd8c8e9ee12203c54b971aece1d920993eececec3ff493e131f63f04c7c4
MD5 4cd955d7959cd049fb89c932281eb0cf
BLAKE2b-256 d98e2531f86b9f23d0607309bcdd6ed60630dfcf57fbd5b9160d9094e001e2ef

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 0623bdc6a0318509fd13bec659ddc697cf02010588bf164b4687c7d8936760cc
MD5 2908c36663e2db2ad9c9b36f9f3e122b
BLAKE2b-256 25294d4e084fad1eb13308c2599e9f2541c758272ac8b491761a78a9d1fb433f

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp310-cp310-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp310-cp310-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 c114b5c5abb0fcb3ccb7241bb53beb051b60863243be1d68f38e184e266b9f87
MD5 944ccc327f65a588753db0dbc90b28ce
BLAKE2b-256 a129a9794ec9a91175a349b1130ed8f4b317ee92ac02de9cbc71b2a20535a191

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: usearch-0.21.0-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 190.1 kB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/4.0.2 CPython/3.11.4

File hashes

Hashes for usearch-0.21.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 1f6902f4e4fb95d123c8ba6e32d7a445a269d1ad60452629c2adbae67fe15f1e
MD5 ef3cdfdaf1408f522533e934d0d84253
BLAKE2b-256 df44d8472731862e947cc854e2b3904089b3b895618a5ffb3599a5eb6a881edc

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp39-cp39-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp39-cp39-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 6757328dd2ab1e28562861a91d6ab882fcefb8cef0f16002635161361435e4ac
MD5 53952a0319b7191ad2e5f3e8ee7c4c52
BLAKE2b-256 5d996afefea3eb4137e25602a434d14324b4338e82ffbb42baa582887ad3db31

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp39-cp39-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp39-cp39-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 104d5c753b339d54c31b6278f5e1e591912ac2ada17fd9cffedbebe91efc45de
MD5 07f438a17490e0fcf5930e0a99352dd9
BLAKE2b-256 e01bc9aaaa4fdc3d66a20e26f5ddaf76e9dafbf19afae7380cebdbb0cee3ba11

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f8fb463132269ab775ae5afd0ddf6ec59dad72b5f44f29965beb36bd0aac9678
MD5 219f790c423d361e5b8952c22abf3e4b
BLAKE2b-256 c94dba977e59637848d109ae6ce7134b15c32f9baeb3c5848c4a7b10ef68371c

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp39-cp39-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 9ff0a1495ed496b55c7df71b2b707f0e28e5471704301b1e0ce1efbd1e348bc1
MD5 97252db13323af43d7cfd30964b3f54c
BLAKE2b-256 dab73847384c4067fa2e61ca1ca93714c706e46aebaedcc407f8a9fa09bec153

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp39-cp39-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 4d4aaf72a600978d9a166916d7d174af0ff494fd3bdc780642f72d7ba2beedc9
MD5 be5d74836b118d14100d55e87ec891d4
BLAKE2b-256 3e42c2f8b54a9757f4a1981e17de8169874e09b98a71610bb0eb7ed5315b5b9a

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp38-cp38-win_amd64.whl.

File metadata

  • Download URL: usearch-0.21.0-cp38-cp38-win_amd64.whl
  • Upload date:
  • Size: 189.9 kB
  • Tags: CPython 3.8, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/4.0.2 CPython/3.11.4

File hashes

Hashes for usearch-0.21.0-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 1d1df3ce3c1910858722ea2ac6776a1781c46b7b8c4af4dc1e6d3c073f848550
MD5 531bf71aa53f4b0b2bd0943e3adbda7a
BLAKE2b-256 0bd11f539f29d2f154e5c1dffad8acbb078103ef512844694e5a50efa151d61d

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp38-cp38-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp38-cp38-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 9758fd8e4d74c11c76cbd05a999d2a90dfb3a79e83c143f5c70c918adaff47b1
MD5 85b4a6346a975da045dd8a2f02fb278d
BLAKE2b-256 a2fadbd73fe57496a3362502a4dabb22422f19d560a3354a9d8aee7ae4dec0a6

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp38-cp38-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp38-cp38-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 7a2ad81ab32bc14833434344914dbbd5dddd0fe3170e48485b723fdc06713d17
MD5 0d864be4ad2cd4ffecf4e5f2d7096336
BLAKE2b-256 b9d9322aa088f61005af5e22b8302cacf8c245c6a03b915decf25aa9ffeeec15

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp38-cp38-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a748e7f25fce67335cdf0d32522969d77c2523a4ef5e09cc8a4fb556685d6436
MD5 fde5a097ca2f6489b20df881de04ba45
BLAKE2b-256 abfd715dc07d398695894acba8f8cfe19de500c6a06cccabee5f69a8b1f3aefc

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp38-cp38-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 2067aaaf75b7ae4f53c6a93a76be7114a78412c686ce4491233bfe26da0fad8d
MD5 7c7a7610ca5140440944e882435122ed
BLAKE2b-256 72b25da8991b86b090dec592741748dcc65c2f2ef1095bfb5cea6a115713b8a6

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp38-cp38-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp38-cp38-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 ec97f51977e7c44c635193714f9e90608fe30269456604c1567bd14dc2a06270
MD5 3bc50165cdd2c67d11aa3937250a97fc
BLAKE2b-256 fd3bf28f71c1a76b831572babbcedfcb05cf9f3fa29ebc1e4edf8f29edd89b76

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp37-cp37m-win_amd64.whl.

File metadata

  • Download URL: usearch-0.21.0-cp37-cp37m-win_amd64.whl
  • Upload date:
  • Size: 190.3 kB
  • Tags: CPython 3.7m, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/4.0.2 CPython/3.11.4

File hashes

Hashes for usearch-0.21.0-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 e7108d0780de416c61a075475b6fc1f71ab1668858e79c43975d39b668c774ed
MD5 fb1157f965bf2177aefc4170298e6f6d
BLAKE2b-256 4afda840e18a8c2a57d209c62abcf451ab9db6871b7311f26514a3137f7a5d90

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp37-cp37m-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp37-cp37m-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c96c948d08d41676c8cfd8bb0a639fcfeb12544789b89ae8e524d02f18f02a99
MD5 dfca3052ecd8015367699ab5b2b5458f
BLAKE2b-256 5ed503b6be0e44b2dcf94212646abaae483a6e2dd585b5384cb942432ecf5f67

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp37-cp37m-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp37-cp37m-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 0cf4b8a324e2a9b61effa0931a19d1ae4cda1cf44fdeefe9259adf83e210c864
MD5 550b1566d2042d47f29136edf2b291c2
BLAKE2b-256 815c8c920b27789745ce1dc2023b5bc5e42021a846d9e0e4c5dee167750cf92e

See more details on using hashes here.

File details

Details for the file usearch-0.21.0-cp37-cp37m-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for usearch-0.21.0-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 cd4e777504cd11fbd49dfdc5dfd46a99979f7787391eb4350fdfd0e359455a30
MD5 a24808149f51a64edf360247db2f8147
BLAKE2b-256 4d950214ee5965c12b1734e22e289b3a451c9d6511a25182831660aa9b226a6e

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page