Package: simsimd
SimSIMD 📏Hardware-Accelerated Similarity Metrics and Distance FunctionsZero-dependencyheader-only C 99library.Handlesf64double-,f32single-, andf16half-precision,i8integral, and binary vectors.Targets ARM NEON, SVE, x86 AVX2, AVX-512 (VNNI, FP16) hardware backends.Bindings forPython,RustandJavaScript.Up to 200x fasterthanscipy.spatial.distanceandnumpy.inner.Supports more Python versionsthan SciPy and NumPy.Zero-copy compatible with NumPy, PyTorch, TensorFlow, and other tensors.Used inUSearchand several DBMS products.Implemented distance functionsinclude:Euclidean (L2), Inner Distance, and Cosine (Angular) spatial distances.Hamming (~ Manhattan) and Jaccard (~ Tanimoto) binary distances.Kullback-Leibler and Jensen–Shannon divergences for probability distributions.Technical Insightsand related articles:Uses Horner's method for polynomial approximations, beating GCC 12 by 119x.Uses Arm SVE and x86 AVX-512's masked loads to eliminate tailfor-loops.Uses AVX-512 FP16 for half-precision operations, that few compilers vectorize.Substitutes LibC'ssqrtcalls with bithacks using Jan Kadlec's constant.For Python avoids slow PyBind11, SWIG, and evenPyArg_ParseTuplefor speed.For JavaScript uses typed arrays and NAPI for zero-copy calls.BenchmarksApple M2 ProGiven 1000 embeddings from OpenAI Ada API with 1536 dimensions, running on the Apple M2 Pro Arm CPU with NEON support, here's how SimSIMD performs against conventional methods:Kindf32improvementf16improvementi8improvementConventional methodSimSIMDCosine32 x79 x133 xscipy.spatial.distance.cosinecosineEuclidean ²5 x26 x17 xscipy.spatial.distance.sqeuclideansqeuclideanInner Distance2 x9 x18 xnumpy.innerinnerJensen Shannon31 x53 xscipy.spatial.distance.jensenshannonjensenshannonIntel Sapphire RapidsOn the Intel Sapphire Rapids platform, SimSIMD was benchmarked against auto-vectorized code using GCC 12. GCC handles single-precisionfloatbut might not be the best choice forint8and_Float16arrays, which has been part of the C language since 2011.KindGCC 12f32GCC 12f16SimSIMDf16f16improvementCosine3.28 M/s336.29 k/s6.88 M/s20 xEuclidean ²4.62 M/s147.25 k/s5.32 M/s36 xInner Distance3.81 M/s192.02 k/s5.99 M/s31 xJensen Shannon1.18 M/s18.13 k/s2.14 M/s118 xBroader Benchmarking Results:Apple M2 Pro.4th Gen Intel Xeon Platinum.AWS Graviton 3.Using SimSIMD in PythonThe package is intended to replace the usage ofnumpy.inner,numpy.dot, andscipy.spatial.distance.
Aside from drastic performance improvements, SimSIMD significantly improves accuracy in mixed precision setups.
NumPy and SciPy, processingi8orf16vectors, will use the same types for accumulators, while SimSIMD can combinei8enumeration,i16multiplication, andi32accumulation to entirely avoid overflows.
The same applies to processingf16values withf32precision.InstallationpipinstallsimsimdDistance Between 2 Vectorsimportsimsimdimportnumpyasnpvec1=np.random.randn(1536).astype(np.float32)vec2=np.random.randn(1536).astype(np.float32)dist=simsimd.cosine(vec1,vec2)Supported functions includecosine,inner,sqeuclidean,hamming, andjaccard.Distance Between 2 Batchesbatch1=np.random.randn(100,1536).astype(np.float32)batch2=np.random.randn(100,1536).astype(np.float32)dist=simsimd.cosine(batch1,batch2)If either batch has more than one vector, the other batch must have one or the same number of vectors.
If it contains just one, the value is broadcasted.All Pairwise DistancesFor calculating distances between all possible pairs of rows across two matrices (akin toscipy.spatial.distance.cdist):matrix1=np.random.randn(1000,1536).astype(np.float32)matrix2=np.random.randn(10,1536).astype(np.float32)distances=simsimd.cdist(matrix1,matrix2,metric="cosine")MultithreadingBy default, computations use a single CPU core. To optimize and utilize all CPU cores on Linux systems, add thethreads=0argument. Alternatively, specify a custom number of threads:distances=simsimd.cdist(matrix1,matrix2,metric="cosine",threads=0)Hardware Backend CapabilitiesTo view a list of hardware backends that SimSIMD supports:print(simsimd.get_capabilities())Using Python API with USearchWant to use it in Python withUSearch?
You can wrap the raw C function pointers SimSIMD backends into aCompiledMetricand pass it to USearch, similar to how it handles Numba's JIT-compiled code.fromusearch.indeximportIndex,CompiledMetric,MetricKind,MetricSignaturefromsimsimdimportpointer_to_sqeuclidean,pointer_to_cosine,pointer_to_innermetric=CompiledMetric(pointer=pointer_to_cosine("f16"),kind=MetricKind.Cos,signature=MetricSignature.ArrayArraySize,)index=Index(256,metric=metric)Using SimSIMD in RustTo install, add the following to yourCargo.toml:[dependencies]simsimd="..."To use it:usesimsimd::{cosine,sqeuclidean};fnmain(){letvector_a=vec![1.0,2.0,3.0];letvector_b=vec![4.0,5.0,6.0];letdistance=cosine(&vector_a,&vector_b);println!("Cosine Distance: {}",distance);letdistance=sqeuclidean(&vector_a,&vector_b);println!("Squared Euclidean Distance: {}",distance);}Using SimSIMD in JavaScriptTo install, choose one of the following options depending on your environment:npm install --save simsimdyarn add simsimdpnpm add simsimdbun install simsimdThe package is distributed with prebuilt binaries for Node.js v10 and above for Linux (x86_64, arm64), macOS (x86_64, arm64), and Windows (i386,x86_64).If your platform is not supported, you can build the package from source vianpm run build. This will automatically happen unless you install the package with--ignore-scriptsflag or use Bun.After you install it, you will be able to call the SimSIMD functions on variousTypedArrayvariants:const{sqeuclidean,cosine,inner,hamming,jaccard}=require('simsimd');constvectorA=newFloat32Array([1.0,2.0,3.0]);constvectorB=newFloat32Array([4.0,5.0,6.0]);constdistance=sqeuclidean(vectorA,vectorB);console.log('Squared Euclidean Distance:',distance);Using SimSIMD in CFor integration within a CMake-based project, add the following segment to yourCMakeLists.txt:FetchContent_Declare(simsimdGIT_REPOSITORYhttps://github.com/ashvardanian/simsimd.gitGIT_SHALLOWTRUE)FetchContent_MakeAvailable(simsimd)If you're aiming to utilize the_Float16functionality with SimSIMD, ensure your development environment is compatible with C 11.
For other functionalities of SimSIMD, C 99 compatibility will suffice.
A minimal usage example would be:#include<simsimd/simsimd.h>intmain(){simsimd_f32_tvector_a[1536];simsimd_f32_tvector_b[1536];simsimd_f32_tdistance=simsimd_avx512_f32_cos(vector_a,vector_b,1536);return0;}All of the functions names follow the same pattern:simsimd_{backend}_{type}_{metric}.The backend can beavx512,avx2,neon, orsve.The type can bef64,f32,f16,i8, orb8.The metric can becos,ip,l2sq,hamming,jaccard,kl, orjs.In case you want to avoid hard-coding the backend, you can use thesimsimd_metric_punned_tto pun the function pointer, andsimsimd_capabilitiesfunction to get the available backends at runtime.