Python Vector Distance API ReferenceΒΆ

OverviewΒΆ

HyperStreamDB provides a comprehensive Python API for vector distance computations with GPU acceleration support across multiple hardware backends. This API allows you to compute distances between vectors directly from Python without writing SQL queries, with optional GPU acceleration for high-performance batch operations.

[!NOTE] This guide covers standalone distance functions for CPU/GPU. For persistent vector storage and search with TurboQuant indexing (TQ8/TQ4), please see Vector Configuration.

Supported Distance MetricsΒΆ

The API supports six distance metrics:

Metric

Function

Description

Use Case

L2 (Euclidean)

l2_distance()

√Σ(a-b)²

General-purpose similarity

Cosine

cosine_distance()

1 - (aΒ·b)/(β€–aβ€–β€–bβ€–)

Text embeddings, normalized vectors

Inner Product

inner_product()

-aΒ·b

Maximum similarity search

L1 (Manhattan)

l1_distance()

Ξ£|a-b|

Robust to outliers

Hamming

hamming_distance()

Count of differing bits

Binary vectors, hashing

Jaccard

jaccard_distance()

1 - |A∩B|/|AβˆͺB|

Set similarity

GPU Backend SupportΒΆ

Supported HardwareΒΆ

Backend

Hardware

Platform

Status

CUDA

NVIDIA GPUs

Linux, WSL2

βœ… Supported

ROCm

AMD GPUs

Linux

βœ… Supported

Metal (MPS)

Apple Silicon

macOS

βœ… Supported

Intel XPU

Intel GPUs

Linux

βœ… Supported

CPU

All platforms

Fallback

βœ… Always available

Backend PriorityΒΆ

When using GPUContext.auto_detect(), backends are selected in this priority order:

  1. CUDA (NVIDIA)

  2. Metal/MPS (Apple Silicon)

  3. ROCm (AMD)

  4. Intel XPU (via WGPU)

  5. CPU (fallback)

InstallationΒΆ

Basic InstallationΒΆ

pip install hyperstreamdb

GPU Backend RequirementsΒΆ

NVIDIA CUDAΒΆ

Requirements:

  • NVIDIA GPU with compute capability 6.0+ (Pascal or newer)

  • CUDA Toolkit 11.0 or later

  • NVIDIA driver 450.80.02 or later

Installation (Linux):

# Ubuntu/Debian
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb
sudo apt-get update
sudo apt-get install cuda-toolkit-12-3

# Verify installation
nvidia-smi
nvcc --version

Installation (Windows via WSL2):

  1. Install WSL2 and a Linux distribution (e.g., Ubuntu 22.04)

  2. Install NVIDIA drivers on the Windows host

  3. Install NVIDIA Container Toolkit or the CUDA Toolkit within WSL2

  4. Follow the Linux installation instructions above within your WSL2 environment

AMD ROCmΒΆ

Requirements:

  • AMD GPU (Radeon RX 5000 series or newer, or Radeon Instinct)

  • ROCm 5.0 or later

  • Linux only (Ubuntu 20.04/22.04, RHEL 8/9)

Installation (Ubuntu):

# Add ROCm repository
wget https://repo.radeon.com/amdgpu-install/latest/ubuntu/jammy/amdgpu-install_5.7.50700-1_all.deb
sudo apt-get install ./amdgpu-install_5.7.50700-1_all.deb

# Install ROCm
sudo amdgpu-install --usecase=rocm

# Add user to video and render groups
sudo usermod -a -G video,render $USER

# Verify installation
rocm-smi

Apple Metal (MPS)ΒΆ

Requirements:

  • Apple Silicon Mac (M1, M2, M3, M4, M5, or newer)

  • macOS 12.3 or later

  • No additional installation required

Verification:

import hyperstreamdb as hdb
ctx = hdb.GPUContext.auto_detect()
print(ctx.backend)  # Should show "mps" on Apple Silicon

Intel XPU (WGPU)ΒΆ

Requirements:

  • Intel GPU (Iris Xe or newer recommended) Installation (Linux / WSL2): Intel hardware is supported natively via WGPU. Ensure you have modern graphics drivers and the vulkan-loader installed.

# Ubuntu/Debian
sudo apt-get install vulkan-tools
vulkaninfo | grep vendor

Quick StartΒΆ

Basic Distance ComputationΒΆ

import hyperstreamdb as hdb
import numpy as np

# Create two vectors
vec1 = np.array([1.0, 2.0, 3.0])
vec2 = np.array([4.0, 5.0, 6.0])

# Compute L2 distance
distance = hdb.l2_distance(vec1, vec2)
print(f"L2 distance: {distance}")

# Compute cosine distance
distance = hdb.cosine_distance(vec1, vec2)
print(f"Cosine distance: {distance}")

GPU-Accelerated Batch OperationsΒΆ

import hyperstreamdb as hdb
import numpy as np

# Create GPU context (auto-detect best backend)
ctx = hdb.GPUContext.auto_detect()
print(f"Using backend: {ctx.backend}")

# Create query vector and database
query = np.random.randn(768).astype(np.float32)
database = np.random.randn(100000, 768).astype(np.float32)

# Compute distances on GPU (10x+ faster for large databases)
distances = hdb.l2_distance_batch(query, database, context=ctx)

# Find top-k nearest neighbors
k = 10
top_k_indices = np.argsort(distances)[:k]
top_k_distances = distances[top_k_indices]

print(f"Top {k} nearest neighbors:")
for idx, dist in zip(top_k_indices, top_k_distances):
    print(f"  Index {idx}: distance {dist:.4f}")

Sparse Vector OperationsΒΆ

import hyperstreamdb as hdb
import numpy as np

# Create sparse vectors (only store non-zero elements)
# Useful for high-dimensional sparse data (e.g., TF-IDF, bag-of-words)
sparse1 = hdb.SparseVector(
    indices=np.array([0, 5, 100, 500], dtype=np.int32),
    values=np.array([1.0, 2.5, 0.8, 3.2], dtype=np.float32),
    dim=1000
)

sparse2 = hdb.SparseVector(
    indices=np.array([5, 50, 100, 600], dtype=np.int32),
    values=np.array([2.0, 1.5, 0.9, 2.1], dtype=np.float32),
    dim=1000
)

# Compute sparse distance (only processes non-zero elements)
distance = hdb.l2_distance_sparse(sparse1, sparse2)
print(f"Sparse L2 distance: {distance}")

# Convert to dense if needed
dense1 = sparse1.to_dense()

Binary Vector OperationsΒΆ

import hyperstreamdb as hdb
import numpy as np

# Binary vectors for efficient similarity search
# Each bit represents a feature (e.g., SimHash, LSH)

# Create bit-packed binary vectors (8 bits per byte)
binary1 = np.packbits(np.random.randint(0, 2, 128))  # 128 bits = 16 bytes
binary2 = np.packbits(np.random.randint(0, 2, 128))

# Compute Hamming distance (counts differing bits)
distance = hdb.hamming_distance_packed(binary1, binary2)
print(f"Hamming distance: {distance} bits differ")

# Compute Jaccard distance for binary vectors
distance = hdb.jaccard_distance_packed(binary1, binary2)
print(f"Jaccard distance: {distance}")

# Auto-packing: provide unpacked binary vectors (0/1 values)
# The API will automatically pack them for efficiency
unpacked1 = np.random.randint(0, 2, 128, dtype=np.uint8)
unpacked2 = np.random.randint(0, 2, 128, dtype=np.uint8)
distance = hdb.hamming_distance(unpacked1, unpacked2)  # Auto-packed internally

API ReferenceΒΆ

Distance FunctionsΒΆ

Single-Pair Distance FunctionsΒΆ

All single-pair functions accept two vectors and return a scalar distance:

l2_distance(vec1, vec2, context=None) -> float
cosine_distance(vec1, vec2, context=None) -> float
inner_product(vec1, vec2, context=None) -> float
l1_distance(vec1, vec2, context=None) -> float
hamming_distance(vec1, vec2, context=None) -> float
jaccard_distance(vec1, vec2, context=None) -> float

Parameters:

  • vec1, vec2: NumPy arrays, Python lists, or any array-like objects

  • context (optional): GPUContext for GPU acceleration

Returns: float - The computed distance

Raises:

  • ValueError: If vectors have different dimensions

  • ValueError: If vectors contain NaN or infinite values

  • TypeError: If input types are invalid

Batch Distance FunctionsΒΆ

Compute distances between one query vector and multiple database vectors:

l2_distance_batch(query, database, context=None) -> np.ndarray
cosine_distance_batch(query, database, context=None) -> np.ndarray
inner_product_batch(query, database, context=None) -> np.ndarray
l1_distance_batch(query, database, context=None) -> np.ndarray
hamming_distance_batch(query, database, context=None) -> np.ndarray
jaccard_distance_batch(query, database, context=None) -> np.ndarray

Parameters:

  • query: 1D NumPy array (shape: [dim])

  • database: 2D NumPy array (shape: [n_vectors, dim])

  • context (optional): GPUContext for GPU acceleration

Returns: np.ndarray - 1D array of distances (shape: [n_vectors])

Performance: GPU acceleration provides 10x+ speedup for databases with 100,000+ vectors

Sparse Distance FunctionsΒΆ

Efficient distance computation for sparse vectors:

l2_distance_sparse(sparse1, sparse2, context=None) -> float
cosine_distance_sparse(sparse1, sparse2, context=None) -> float
inner_product_sparse(sparse1, sparse2, context=None) -> float

Parameters:

  • sparse1, sparse2: SparseVector objects

  • context (optional): GPUContext for GPU acceleration

Returns: float - The computed distance

Binary Distance FunctionsΒΆ

Efficient distance computation for bit-packed binary vectors:

hamming_distance_packed(binary1, binary2, context=None) -> int
jaccard_distance_packed(binary1, binary2, context=None) -> float

Parameters:

  • binary1, binary2: NumPy uint8 arrays (bit-packed)

  • context (optional): GPUContext for GPU acceleration

Returns: Distance value (int for Hamming, float for Jaccard)

GPU Context ManagementΒΆ

GPUContext ClassΒΆ

class GPUContext:
    """Manages GPU backend selection and device configuration."""
    
    @staticmethod
    def auto_detect() -> GPUContext:
        """Detect and return the highest-priority available GPU backend."""
    
    def __init__(self, backend: str, device_id: int = 0):
        """
        Create GPU context with specific backend.
        
        Args:
            backend: Backend name ("cuda", "rocm", "mps", "intel", "cpu")
            device_id: GPU device ID for multi-GPU systems (default: 0)
        
        Raises:
            RuntimeError: If backend is not available
        """
    
    @property
    def backend(self) -> str:
        """Get current backend name."""
    
    @property
    def device_id(self) -> int:
        """Get current device ID."""
    
    def list_available_backends(self) -> list[str]:
        """List all detected GPU backends."""
    
    def get_stats(self) -> dict:
        """
        Get performance statistics.
        
        Returns:
            dict with keys:
                - total_gpu_time_ms: Total GPU computation time
                - kernel_launches: Number of GPU kernel launches
                - vectors_processed: Total vectors processed
        """
    
    def reset_stats(self):
        """Clear all accumulated performance metrics."""

Usage ExamplesΒΆ

# Auto-detect best backend
ctx = hdb.GPUContext.auto_detect()

# Create specific backend
ctx = hdb.GPUContext("cuda", device_id=0)

# List available backends
backends = ctx.list_available_backends()
print(f"Available backends: {backends}")

# Monitor performance
distances = hdb.l2_distance_batch(query, database, context=ctx)
stats = ctx.get_stats()
print(f"GPU time: {stats['total_gpu_time_ms']}ms")
print(f"Kernel launches: {stats['kernel_launches']}")

# Reset stats for next benchmark
ctx.reset_stats()

Sparse Vector ClassΒΆ

class SparseVector:
    """Sparse vector representation storing only non-zero elements."""
    
    def __init__(self, indices: np.ndarray, values: np.ndarray, dim: int):
        """
        Create sparse vector.
        
        Args:
            indices: 1D int32 array of non-zero indices (must be sorted)
            values: 1D float32 array of non-zero values
            dim: Total dimension of the vector
        
        Raises:
            ValueError: If indices are not sorted or out of bounds
        """
    
    @property
    def indices(self) -> np.ndarray:
        """Get non-zero indices."""
    
    @property
    def values(self) -> np.ndarray:
        """Get non-zero values."""
    
    @property
    def dim(self) -> int:
        """Get total dimension."""
    
    def to_dense(self) -> np.ndarray:
        """Convert to dense NumPy array."""

Performance OptimizationΒΆ

When to Use GPU AccelerationΒΆ

GPU acceleration provides significant speedups for:

  • Batch operations with 10,000+ vectors

  • High-dimensional vectors (512+ dimensions)

  • Repeated queries on the same database

For small operations (< 1,000 vectors), CPU may be faster due to GPU transfer overhead.

Memory ConsiderationsΒΆ

GPU memory limits:

  • NVIDIA RTX 3090: 24 GB

  • Apple M1 Max: 32-64 GB (shared)

  • AMD RX 7900 XTX: 24 GB

For large databases, consider:

  1. Batch processing: Process database in chunks

  2. Sparse vectors: Reduce memory usage for sparse data

  3. Binary vectors: Use bit-packing for binary features

Best PracticesΒΆ

# βœ… Good: Reuse GPU context
ctx = hdb.GPUContext.auto_detect()
for query in queries:
    distances = hdb.l2_distance_batch(query, database, context=ctx)

# ❌ Bad: Create new context each time
for query in queries:
    ctx = hdb.GPUContext.auto_detect()  # Overhead!
    distances = hdb.l2_distance_batch(query, database, context=ctx)

# βœ… Good: Use appropriate data types
query = np.array(data, dtype=np.float32)  # float32 is faster on GPU

# ❌ Bad: Use float64 unnecessarily
query = np.array(data, dtype=np.float64)  # Slower and uses more memory

Integration with SQLΒΆ

The Python API shares the same GPU context with SQL queries:

import hyperstreamdb as hdb

# Set global GPU context
ctx = hdb.GPUContext.auto_detect()
hdb.set_thread_gpu_context(ctx)

# SQL queries now use GPU acceleration
session = hdb.Session()
session.register("documents", table)

results = session.sql("""
    SELECT id, content,
           embedding <-> '[0.1, 0.2, 0.3]'::vector AS distance
    FROM documents
    ORDER BY distance
    LIMIT 10
""")

# Check GPU usage
stats = ctx.get_stats()
print(f"GPU time: {stats['total_gpu_time_ms']}ms")

TroubleshootingΒΆ

GPU Not DetectedΒΆ

ctx = hdb.GPUContext.auto_detect()
print(ctx.backend)  # Shows "cpu" instead of GPU backend

Solutions:

  1. Verify GPU drivers are installed: nvidia-smi, rocm-smi, or check System Preferences on macOS

  2. Check backend availability: ctx.list_available_backends()

  3. Verify CUDA/ROCm installation: nvcc --version or rocminfo

Out of Memory ErrorsΒΆ

# Error: RuntimeError: GPU out of memory
distances = hdb.l2_distance_batch(query, huge_database, context=ctx)

Solutions:

# Process in chunks
chunk_size = 10000
all_distances = []
for i in range(0, len(database), chunk_size):
    chunk = database[i:i+chunk_size]
    distances = hdb.l2_distance_batch(query, chunk, context=ctx)
    all_distances.append(distances)
all_distances = np.concatenate(all_distances)

Dimension MismatchΒΆ

# Error: ValueError: Vector dimensions must match
distance = hdb.l2_distance(vec1, vec2)

Solutions:

# Check dimensions
print(f"vec1 shape: {vec1.shape}, vec2 shape: {vec2.shape}")

# Ensure same dimension
assert vec1.shape == vec2.shape

ExamplesΒΆ

See examples/python_distance_api_examples.py for complete working examples.

See AlsoΒΆ

  • pgvector SQL Guide - SQL syntax for vector operations

  • Vector Configuration - Index configuration and tuning

  • Benchmarking Guide - Performance testing and optimization