mirror of
https://github.com/ruvnet/RuVector.git
synced 2026-05-26 07:44:05 +00:00
fix: batch 1 — deadlock, AVX-512 gating, Windows case-collisions
Closes #437: VectorDb::delete in ruvector-router-core acquired the stats RwLock twice in one statement. parking_lot::RwLock is non-reentrant, so the second .write() deadlocked against the first guard's lifetime. Bind the guard once. Closes #438: Gate AVX-512 intrinsics behind a new `simd-avx512` Cargo feature (default-on). Lets downstream consumers on stable Rust 1.77–1.88 (before avx512f stabilization in 1.89) opt out without forcing nightly: cargo build --no-default-features --features simd,storage,hnsw,api-embeddings,parallel Runtime dispatch falls back to AVX2 + FMA when the feature is disabled. All 4 #[target_feature(enable = "avx512f")] sites + 4 dispatch branches updated. Both feature configurations verified to compile cleanly; all 18 simd_intrinsics tests pass. Closes #458: Rename two pairs of case-colliding research artifacts under docs/research/claude-code-rvsource/versions/v2.1.x/tree/react_memo_cache_sentinel/ that broke `git clone` on Windows/NTFS: tmux.js → tmux_lc.js (TMUX.js kept) type.js → type_lc.js (Type.js kept) modules-manifest.json updated to match. Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
parent
9054c2cc67
commit
0fa88d61b2
6 changed files with 42 additions and 20 deletions
|
|
@ -95,8 +95,13 @@ name = "bench_memory"
|
|||
harness = false
|
||||
|
||||
[features]
|
||||
default = ["simd", "storage", "hnsw", "api-embeddings", "parallel"]
|
||||
default = ["simd", "simd-avx512", "storage", "hnsw", "api-embeddings", "parallel"]
|
||||
simd = ["simsimd"] # SIMD acceleration (not available in WASM)
|
||||
# AVX-512 intrinsics. Requires Rust >= 1.89 (where avx512f stabilized).
|
||||
# Downstream consumers on older stable (1.77–1.88) can opt out:
|
||||
# --no-default-features --features simd,storage,hnsw,api-embeddings,parallel
|
||||
# See issue #438.
|
||||
simd-avx512 = []
|
||||
parallel = ["rayon", "crossbeam"] # Parallel processing (not available in WASM)
|
||||
storage = ["redb", "memmap2"] # File-based storage (not available in WASM)
|
||||
hnsw = ["hnsw_rs"] # HNSW indexing (not available in WASM due to mmap dependency)
|
||||
|
|
|
|||
|
|
@ -42,9 +42,13 @@ const PREFETCH_DISTANCE: usize = 64;
|
|||
pub fn euclidean_distance_simd(a: &[f32], b: &[f32]) -> f32 {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
if is_x86_feature_detected!("avx512f") {
|
||||
unsafe { euclidean_distance_avx512_impl(a, b) }
|
||||
} else if is_x86_feature_detected!("avx2") && is_x86_feature_detected!("fma") {
|
||||
#[cfg(feature = "simd-avx512")]
|
||||
{
|
||||
if is_x86_feature_detected!("avx512f") {
|
||||
return unsafe { euclidean_distance_avx512_impl(a, b) };
|
||||
}
|
||||
}
|
||||
if is_x86_feature_detected!("avx2") && is_x86_feature_detected!("fma") {
|
||||
unsafe { euclidean_distance_avx2_fma_impl(a, b) }
|
||||
} else if is_x86_feature_detected!("avx2") {
|
||||
unsafe { euclidean_distance_avx2_impl(a, b) }
|
||||
|
|
@ -192,7 +196,7 @@ unsafe fn euclidean_distance_avx2_fma_impl(a: &[f32], b: &[f32]) -> f32 {
|
|||
// ============================================================================
|
||||
|
||||
/// AVX-512 euclidean distance - processes 16 floats per iteration
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(all(target_arch = "x86_64", feature = "simd-avx512"))]
|
||||
#[target_feature(enable = "avx512f")]
|
||||
unsafe fn euclidean_distance_avx512_impl(a: &[f32], b: &[f32]) -> f32 {
|
||||
assert_eq!(a.len(), b.len(), "Input arrays must have the same length");
|
||||
|
|
@ -223,7 +227,7 @@ unsafe fn euclidean_distance_avx512_impl(a: &[f32], b: &[f32]) -> f32 {
|
|||
}
|
||||
|
||||
/// AVX-512 dot product - processes 16 floats per iteration
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(all(target_arch = "x86_64", feature = "simd-avx512"))]
|
||||
#[target_feature(enable = "avx512f")]
|
||||
unsafe fn dot_product_avx512_impl(a: &[f32], b: &[f32]) -> f32 {
|
||||
assert_eq!(a.len(), b.len(), "Input arrays must have the same length");
|
||||
|
|
@ -249,7 +253,7 @@ unsafe fn dot_product_avx512_impl(a: &[f32], b: &[f32]) -> f32 {
|
|||
}
|
||||
|
||||
/// AVX-512 cosine similarity - processes 16 floats per iteration
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(all(target_arch = "x86_64", feature = "simd-avx512"))]
|
||||
#[target_feature(enable = "avx512f")]
|
||||
unsafe fn cosine_similarity_avx512_impl(a: &[f32], b: &[f32]) -> f32 {
|
||||
assert_eq!(a.len(), b.len(), "Input arrays must have the same length");
|
||||
|
|
@ -284,7 +288,7 @@ unsafe fn cosine_similarity_avx512_impl(a: &[f32], b: &[f32]) -> f32 {
|
|||
}
|
||||
|
||||
/// AVX-512 Manhattan distance - processes 16 floats per iteration
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(all(target_arch = "x86_64", feature = "simd-avx512"))]
|
||||
#[target_feature(enable = "avx512f")]
|
||||
unsafe fn manhattan_distance_avx512_impl(a: &[f32], b: &[f32]) -> f32 {
|
||||
assert_eq!(a.len(), b.len(), "Input arrays must have the same length");
|
||||
|
|
@ -783,9 +787,13 @@ unsafe fn manhattan_distance_neon_unrolled_impl(a: &[f32], b: &[f32]) -> f32 {
|
|||
pub fn dot_product_simd(a: &[f32], b: &[f32]) -> f32 {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
if is_x86_feature_detected!("avx512f") {
|
||||
unsafe { dot_product_avx512_impl(a, b) }
|
||||
} else if is_x86_feature_detected!("avx2") {
|
||||
#[cfg(feature = "simd-avx512")]
|
||||
{
|
||||
if is_x86_feature_detected!("avx512f") {
|
||||
return unsafe { dot_product_avx512_impl(a, b) };
|
||||
}
|
||||
}
|
||||
if is_x86_feature_detected!("avx2") {
|
||||
unsafe { dot_product_avx2_impl(a, b) }
|
||||
} else {
|
||||
dot_product_scalar(a, b)
|
||||
|
|
@ -847,9 +855,13 @@ unsafe fn dot_product_avx2_impl(a: &[f32], b: &[f32]) -> f32 {
|
|||
pub fn cosine_similarity_simd(a: &[f32], b: &[f32]) -> f32 {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
if is_x86_feature_detected!("avx512f") {
|
||||
unsafe { cosine_similarity_avx512_impl(a, b) }
|
||||
} else if is_x86_feature_detected!("avx2") {
|
||||
#[cfg(feature = "simd-avx512")]
|
||||
{
|
||||
if is_x86_feature_detected!("avx512f") {
|
||||
return unsafe { cosine_similarity_avx512_impl(a, b) };
|
||||
}
|
||||
}
|
||||
if is_x86_feature_detected!("avx2") {
|
||||
unsafe { cosine_similarity_avx2_impl(a, b) }
|
||||
} else {
|
||||
cosine_similarity_scalar(a, b)
|
||||
|
|
@ -883,9 +895,13 @@ pub fn cosine_similarity_avx2(a: &[f32], b: &[f32]) -> f32 {
|
|||
pub fn manhattan_distance_simd(a: &[f32], b: &[f32]) -> f32 {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
if is_x86_feature_detected!("avx512f") {
|
||||
unsafe { manhattan_distance_avx512_impl(a, b) }
|
||||
} else if is_x86_feature_detected!("avx2") {
|
||||
#[cfg(feature = "simd-avx512")]
|
||||
{
|
||||
if is_x86_feature_detected!("avx512f") {
|
||||
return unsafe { manhattan_distance_avx512_impl(a, b) };
|
||||
}
|
||||
}
|
||||
if is_x86_feature_detected!("avx2") {
|
||||
unsafe { manhattan_distance_avx2_impl(a, b) }
|
||||
} else {
|
||||
manhattan_distance_scalar(a, b)
|
||||
|
|
|
|||
|
|
@ -150,7 +150,8 @@ impl VectorDB {
|
|||
|
||||
if deleted {
|
||||
self.index.remove(id)?;
|
||||
self.stats.write().total_vectors = self.stats.write().total_vectors.saturating_sub(1);
|
||||
let mut stats = self.stats.write();
|
||||
stats.total_vectors = stats.total_vectors.saturating_sub(1);
|
||||
}
|
||||
|
||||
Ok(deleted)
|
||||
|
|
|
|||
|
|
@ -1418,7 +1418,7 @@
|
|||
"size": 387
|
||||
},
|
||||
{
|
||||
"name": "type.js",
|
||||
"name": "type_lc.js",
|
||||
"size": 387
|
||||
},
|
||||
{
|
||||
|
|
@ -2330,7 +2330,7 @@
|
|||
"size": 176
|
||||
},
|
||||
{
|
||||
"name": "tmux.js",
|
||||
"name": "tmux_lc.js",
|
||||
"size": 176
|
||||
},
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue