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 = index.search(fingerprints, 10)

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.20.0-cp311-cp311-win_amd64.whl (177.2 kB view details)

Uploaded CPython 3.11 Windows x86-64

usearch-0.20.0-cp311-cp311-manylinux_2_28_x86_64.whl (334.4 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.28+ x86-64

usearch-0.20.0-cp311-cp311-manylinux_2_28_aarch64.whl (322.1 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.28+ ARM64

usearch-0.20.0-cp311-cp311-macosx_11_0_arm64.whl (227.0 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

usearch-0.20.0-cp311-cp311-macosx_10_9_x86_64.whl (233.1 kB view details)

Uploaded CPython 3.11 macOS 10.9+ x86-64

usearch-0.20.0-cp311-cp311-macosx_10_9_universal2.whl (430.2 kB view details)

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

usearch-0.20.0-cp310-cp310-win_amd64.whl (177.2 kB view details)

Uploaded CPython 3.10 Windows x86-64

usearch-0.20.0-cp310-cp310-manylinux_2_28_x86_64.whl (334.3 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.28+ x86-64

usearch-0.20.0-cp310-cp310-manylinux_2_28_aarch64.whl (322.1 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.28+ ARM64

usearch-0.20.0-cp310-cp310-macosx_11_0_arm64.whl (227.0 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

usearch-0.20.0-cp310-cp310-macosx_10_9_x86_64.whl (233.1 kB view details)

Uploaded CPython 3.10 macOS 10.9+ x86-64

usearch-0.20.0-cp310-cp310-macosx_10_9_universal2.whl (430.3 kB view details)

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

usearch-0.20.0-cp39-cp39-win_amd64.whl (177.2 kB view details)

Uploaded CPython 3.9 Windows x86-64

usearch-0.20.0-cp39-cp39-manylinux_2_28_x86_64.whl (334.4 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.28+ x86-64

usearch-0.20.0-cp39-cp39-manylinux_2_28_aarch64.whl (322.1 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.28+ ARM64

usearch-0.20.0-cp39-cp39-macosx_11_0_arm64.whl (227.2 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

usearch-0.20.0-cp39-cp39-macosx_10_9_x86_64.whl (233.3 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

usearch-0.20.0-cp39-cp39-macosx_10_9_universal2.whl (430.7 kB view details)

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

usearch-0.20.0-cp38-cp38-win_amd64.whl (177.2 kB view details)

Uploaded CPython 3.8 Windows x86-64

usearch-0.20.0-cp38-cp38-manylinux_2_28_x86_64.whl (334.1 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.28+ x86-64

usearch-0.20.0-cp38-cp38-manylinux_2_28_aarch64.whl (321.9 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.28+ ARM64

usearch-0.20.0-cp38-cp38-macosx_11_0_arm64.whl (227.0 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

usearch-0.20.0-cp38-cp38-macosx_10_9_x86_64.whl (233.0 kB view details)

Uploaded CPython 3.8 macOS 10.9+ x86-64

usearch-0.20.0-cp38-cp38-macosx_10_9_universal2.whl (430.1 kB view details)

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

usearch-0.20.0-cp37-cp37m-win_amd64.whl (176.9 kB view details)

Uploaded CPython 3.7m Windows x86-64

usearch-0.20.0-cp37-cp37m-manylinux_2_28_x86_64.whl (340.2 kB view details)

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

usearch-0.20.0-cp37-cp37m-manylinux_2_28_aarch64.whl (328.1 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.28+ ARM64

usearch-0.20.0-cp37-cp37m-macosx_10_9_x86_64.whl (230.4 kB view details)

Uploaded CPython 3.7m macOS 10.9+ x86-64

File details

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

File metadata

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

File hashes

Hashes for usearch-0.20.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 4c3eca3cb5adf4e71dc251b8524bd1a47a4b73680f709a3629d206f1d1114fdf
MD5 55c248c61f6134a90fb24bb23699b680
BLAKE2b-256 0e1fc447a4fcb8da4b1d1de1ed23419ea766865aecc6841e4da7a1dee2e9d408

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1868bb2844d721dd64819468adf8206df38e51ddce426897c589b887b6f448f2
MD5 792eb6b23db257797660f68fd40b1783
BLAKE2b-256 675f8c7f352e3392bb69c02487c8c271d4e4c2751e9aca7d39c5c772e5b2f130

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp311-cp311-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 c274e266783f48cb16a0b5e56b4ea58aca627958e52bba818ee822d9aea02f74
MD5 05928a7d5cc51977ff34c37dab723d12
BLAKE2b-256 c8009f5bed70b22cc61c8331cb7906640ebc86eb248a43c1653000e5bc99f113

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 03bd81eacc7b18d04e78f7c6ba8d83924e83d7b3b2c6f46cd06b19ad2b647eaf
MD5 52e8af033d0a7d3d389c9d078c41b76a
BLAKE2b-256 5454a894bd2d6436491a636b0ef16c6c3af1cb0d64b6cc14ec49f011a04f2aeb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 98c7acc500839f078b405569e99c87e5987de64b03b674f32350089b0a6dbfd2
MD5 545f0ac77b69dacf72815e65a6039c06
BLAKE2b-256 c6c32f589ec6bd76c5decbf84e2dae33c6a25aa63642c2fd617825f8a50d725d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp311-cp311-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 faf6271816d4cff75c4a4f91214dbf356db8154dfaaf298546a192ab746d49fd
MD5 1ee8b7916f2b92482fe9051ed011157e
BLAKE2b-256 b79e9ced5c1825a1ab44b8518383addeba0e3e2c3c35f65df53ea6faf4233548

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for usearch-0.20.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 86b8b5b61457063bf19a91863c954183c18a4286adb0a4a80b3bd88c7153e9e4
MD5 44641b0ee8b0c480e3a9cca4def09b16
BLAKE2b-256 bd1c0cf4d514f146c1ee674f62c7c77f4f201a1865505097769e4ce427e5f09b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp310-cp310-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 081a2cc3843c273eaed3c2a64d57d7caeba26daa36750825a0aadfe31422b930
MD5 e0ce525b3a599e7ba0751ac28659c24e
BLAKE2b-256 9d967cc46257e4da4c45b03721b3a40d6227fecfebe85888170dd1fb7441887a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp310-cp310-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 dc1fedd0e2fa27b68f40da88e64adf9d70d406813ac8b684131cfb0fa690bf84
MD5 ee461080c398d7fddbba479ded6b319e
BLAKE2b-256 153200097befc1c3bdb173559ecf57d2045bfe9dc892c2ef3a787d7b7b5c4d81

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 be7fa89460997bab41eac966ab0cb42c0f504a389853b68e922423ff3ff7c6e7
MD5 0cc35178988e0cb7ce9c52815dd19edc
BLAKE2b-256 430a03ff8bd91b100c1444289259076068e2edf8cf334f06d25172dd19521127

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 dbf600e6c640563be8bd2df50fb4e37c4aece2b123ceaecf4ba1ccc109427582
MD5 808c60e4c80c8ec79cd4d0e45884b7f7
BLAKE2b-256 e54c74c0d062c4e1e8d8d0b41cbf83998489783b855ea15c9b8be01513af8e95

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp310-cp310-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 58d8613944ef53e32395bf04147f0ae9c7b3493120db3db58d09cc029ab07b12
MD5 ae88e1757b53138a4262a6a84ed6fa75
BLAKE2b-256 ac19789344d56fe82e55184f0467194f87a6d3c25443e7560ee7bf94b9df3009

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for usearch-0.20.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 cf34eec3518151dd7806290320636d3ee4a18bcaceb745534ead564cd7cc3a25
MD5 378c5b8be538e097d5467cbfd89d2989
BLAKE2b-256 cdedac043ad26bebfd92785c5cdb9a9ef407f3ae0d24b0b28ede2d8b468e2375

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp39-cp39-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 8116d5ed98eae4cefc142d243bb2e8e5b0cb6d892eb072a1bc43175056b24069
MD5 3adfeb743037f461a59405c32a47263a
BLAKE2b-256 dcd0f264711bb3d4ed252a24d89a980062ee724e3e39410109a630844f0e2f50

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp39-cp39-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 1214f0d73e41496846f1e264656f9ae5acf540b81ca54021ccf52f36dcac1d60
MD5 a1f0c5ba3caebba2bd8d4a4877432f4c
BLAKE2b-256 20e9d5dbf69a335f64b0ee3db4aafbf7e6c93bfd338b5c69ecb63c397daf9efa

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ba6ad62eeffd8a934b78d86e1491dc5163efa3cc1fee23f5fc3026e30301f767
MD5 3051ec8b376a9d3d1bbaece48e4a4ea2
BLAKE2b-256 bd5035db3f65f4a88c434607c48252523247dd3b0822c11266bf48f075ec31a7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 f951a0d7864a1e873b698d04a483a495975e2515f371040d377694bfac686155
MD5 b9de38782dc866cd3ee5d686608f4665
BLAKE2b-256 9b7f7348cff70d82889e878158079997794ef4471ac09f69b73ae91c6b8a4e97

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 a4b56c225c73684bcf281ff94cf9f492ae519ded67bb66f125945df3920b6672
MD5 8e0b24e1a6fa79300f55ec1da271d6bb
BLAKE2b-256 1d0b201a4a64f7356b9698f7cf03a8f537e155bf409a7a4dfd1cd3e6a1208466

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for usearch-0.20.0-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 3a6424265f9cbff0699f39ccb36d2ea33df0bd0c2295e76b6d55749ff6ac0869
MD5 24f9f6c682acc00b9b29b4eefd71eb71
BLAKE2b-256 7c6a1f4cd601089c8ab51b5556de4561f6b238f26aea8a4e4c776a5a99e9ecf4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp38-cp38-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0914ea8eba57f35ae9ba4b2e2a579f5478f21ccfbe3d16be07e04772065192d2
MD5 f7f69086763d8583eb1845d00dac6fe6
BLAKE2b-256 a3226abc9d12d9c61615c0b703f127f43f1f56d7d6e82dc6153b5fba2506d1eb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp38-cp38-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 3c4c32992018ff48cd5924f6fa21631112fc79628a6306976429766c940ae727
MD5 489ddf46a5ba08d395b36a854711c845
BLAKE2b-256 b6e075d8ad0dd16f4025cf432165bd325a4dcfe0c624ca67cfb84e4bc4973e4b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9f69086fc93f0a24764f935ecb8840fc97b7081e2af1663ada24f56ed3046df9
MD5 d77066c50b2ff6e516f975e182b04492
BLAKE2b-256 aebee9fadc73b740b7b945afdb97e1a005ac617086b71e0ce41431ef33ddf3aa

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 c70f4d1f4727ff14cd84a8554433f6eab003b8dac04863f55f6acf8976d9827b
MD5 841ce3f3b5b57495f756990a9b8d67ef
BLAKE2b-256 07d2f3721aaea1d62050580e42b378307b83c15edd9be62fd07928ad7a32ce06

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp38-cp38-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 502270c89537cd548e1f225d27f12ce2935f48303065641a00a9af6e4747d09c
MD5 de5c0d6e25b2e69eec93aeb2dfddb5a1
BLAKE2b-256 486eb6fcd532f7a109fe751c2b0cb5d4dd3d6ecd87015ad63de25ff446d27c4d

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for usearch-0.20.0-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 cf6ce7709be0c63496bbf0dbe5dcbb0c5e7e41a9ffdab8548fe996563c25bdb9
MD5 c3157c2c3cb2de8c6702b67c9c07fa41
BLAKE2b-256 1e34e5f3543ef00ca664b94bab29234996229699261c23ff57f30c2cc3666f16

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp37-cp37m-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 9ee0f91f846787b95a97636ccc3e70c50f9018313772287c5eb3aab3b92b498d
MD5 963ad0b4752df4083d384865455702a8
BLAKE2b-256 b3824a3b16211dceb61491e05243dfc51779b6652275e5c723aa6986b02c9362

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp37-cp37m-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 07d6ae9aabe577a40eee09b9292bbf28c1b18caa44d4e0894e923f070095ecc0
MD5 3e91aab2058eb8758f71bf1413105091
BLAKE2b-256 1d5670a16cae70079601b2620d51967a9b95d083dafd841350cd58938e64eb8c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for usearch-0.20.0-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 6bc9d2738ebd9b0b2705753b90221dab5de243d3395e66f266f6999ab8e0b4f9
MD5 a76158ef8e9f363df7078709ee626454
BLAKE2b-256 09a6a1abe5507b3573c9f6b04839eda13a196baec37bc2f499fd8400aa189306

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