knncolle_hnsw
knncolle bindings for HNSW
|
The knncolle_hnsw library provides knncolle bindings to the HNSW library for approximate nearest neighbors search. This allows users to use HNSW searches in any framework that accepts knncolle interfaces, sacrificing neighbor search accuracy for greater speed. For most applications involving large datasets, this is an acceptable trade-off.
Instances of the various knncolle_hnsw::Hnsw*
classes can be used anywhere that accepts the corresponding knncolle interface. For example:
Check out the reference documentation for more details.
We can also customize the construction of the HnswBuilder
by passing in options or specifying a different distance metric:
We could also modify the builder after construction, which will affect all subsequently constructed indices:
Advanced users can configure the template parameters to use more suitable types for their applications. A hypothetical configuration is shown below with (mostly made up) reasons:
FetchContent
If you're using CMake, you just need to add something like this to your CMakeLists.txt
:
Then you can link to knncolle_hnsw to make the headers available during compilation:
By default, this will use FetchContent
to fetch all external dependencies. Applications are advised to pin the versions of each dependency for stability - see extern/CMakeLists.txt
for suggested versions. If you want to install them manually, use -DKNNCOLLE_HNSW_FETCH_EXTERN=OFF
.
find_package()
To install the library, use:
Again, this will automatically acquire all its dependencies, see recommendations above.
If you're not using CMake, the simple approach is to just copy the files in include/
- either directly or with Git submodules - and include their path during compilation with, e.g., GCC's -I
. This will also require the external dependencies listed in extern/CMakeLists.txt
.
HNSW will attempt to perform manual vectorization based on SSE and/or AVX instructions. This may result in differences in the results across machines due to changes in numeric precision across architectures with varying support for SSE/AVX intrinsics. For the most part, such differences can be avoided by consistently compiling for the "near-lowest common denominator" (such as the typical x86-64
default for GCC and Clang) and ensuring that the more specific instruction subsets like SSE3 and AVX are not enabled (which are typically off by default anyway). Nonetheless, if reproducibility across architectures is important, it can be achieved at the cost of some speed by defining the NO_MANUAL_VECTORIZATION
macro, which will instruct Hnsw to disable its vectorized optimizations.