perf(ann): unit-vector dot product and a reusable visited set
- Cosine distance was 1 - dot/(|a||b|), re-deriving both norms on every evaluation in the innermost loop of build and search. The index now stores unit vectors (prepared at build, insert, graph load and HDF5 load; the query once per search) and uses 1 - dot. Zero vectors stay zero, giving distance 1 as before. Returned distances are unchanged. - search_layer allocated a HashSet of visited nodes per call. It is now an epoch-stamped u32 array in thread-local scratch, reused across calls, so search(&self) stays shareable between threads. - clawhdf5-accel caches the detected SIMD backend in a OnceLock. Recall is identical. Build 2.75 -> 1.89 s (10K), ~38 -> 21 s (100K); QPS at ef=64 22.7K -> 39K (10K), 10.4K -> 14K (100K). Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
09480747aa
commit
f15bf2eb22
@@ -61,8 +61,14 @@ pub enum Backend {
|
||||
Scalar,
|
||||
}
|
||||
|
||||
/// Detect the best available SIMD backend at runtime.
|
||||
/// The best available SIMD backend, detected once per process. Every kernel
|
||||
/// dispatches through this, so it sits in the innermost loop of every search.
|
||||
pub fn detect_backend() -> Backend {
|
||||
static BACKEND: std::sync::OnceLock<Backend> = std::sync::OnceLock::new();
|
||||
*BACKEND.get_or_init(detect_backend_uncached)
|
||||
}
|
||||
|
||||
fn detect_backend_uncached() -> Backend {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
{
|
||||
return Backend::Neon; // Always available on aarch64
|
||||
|
||||
Reference in New Issue
Block a user