Skip to content

Commit 1154cda

Browse files
authored
Remove redundant allocations in distance function (#75)
1 parent 6f7c345 commit 1154cda

2 files changed

Lines changed: 33 additions & 36 deletions

File tree

‎crates/index/src/hnsw/search.rs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ impl HnswIndex {
2323
let mut current = ep;
2424
loop {
2525
let cur_vec = self.get_vec(current)?;
26-
let mut best_score = distance(&query.to_vec(), cur_vec, self.similarity);
26+
let mut best_score = distance(query, cur_vec, self.similarity);
2727
let mut best_id = current;
2828

2929
let empty: &[PointId] = &[];
@@ -46,7 +46,7 @@ impl HnswIndex {
4646
continue;
4747
}
4848
let n_vec = self.get_vec(n)?;
49-
let score = distance(&query.to_vec(), n_vec, self.similarity);
49+
let score = distance(query, n_vec, self.similarity);
5050
if score < best_score {
5151
best_score = score;
5252
best_id = n;
@@ -91,7 +91,7 @@ impl HnswIndex {
9191
.unwrap_or(ep),
9292
};
9393

94-
let ep_score = distance(&query.to_vec(), self.get_vec(seed)?, self.similarity);
94+
let ep_score = distance(query, self.get_vec(seed)?, self.similarity);
9595
candidates.push((Reverse(OrdF32::new(ep_score)), seed));
9696
w_heap.push((OrdF32::new(ep_score), seed));
9797
visited.insert(seed);
@@ -125,7 +125,7 @@ impl HnswIndex {
125125
}
126126

127127
visited.insert(n);
128-
let score = distance(&query.to_vec(), self.get_vec(n)?, self.similarity);
128+
let score = distance(query, self.get_vec(n)?, self.similarity);
129129
let score = OrdF32::new(score);
130130
candidates.push((Reverse(score), n));
131131
if w_heap.len() < ef_construction {

‎crates/index/src/lib.rs‎

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,41 +21,38 @@ pub trait VectorIndex: Send + Sync {
2121
}
2222

2323
/// Distance function to get the distance between two vectors (taken from old version)
24-
pub fn distance(a: &DenseVector, b: &DenseVector, dist_type: Similarity) -> f32 {
24+
pub fn distance(a: &[f32], b: &[f32], dist_type: Similarity) -> f32 {
2525
assert_eq!(a.len(), b.len());
2626
match dist_type {
27-
Similarity::Euclidean => {
28-
let score: Vec<f32> = a
29-
.iter()
30-
.zip(b.iter())
31-
.map(|(&x, &y)| (x - y) * (x - y))
32-
.collect();
33-
score.iter().sum::<f32>().sqrt()
34-
}
35-
Similarity::Manhattan => {
36-
let score: Vec<f32> = a
37-
.iter()
38-
.zip(b.iter())
39-
.map(|(&x, &y)| (x - y).abs())
40-
.collect();
41-
score.iter().sum::<f32>()
42-
}
43-
Similarity::Hamming => {
44-
let score: Vec<f32> = a
45-
.iter()
46-
.zip(b.iter())
47-
.map(|(&x, &y)| if (x - y).abs() > 1e-8 { 1f32 } else { 0f32 })
48-
.collect();
49-
score.iter().sum::<f32>()
50-
}
27+
Similarity::Euclidean => a
28+
.iter()
29+
.zip(b.iter())
30+
.map(|(&x, &y)| {
31+
let d = x - y;
32+
d * d
33+
})
34+
.sum::<f32>()
35+
.sqrt(),
36+
Similarity::Manhattan => a
37+
.iter()
38+
.zip(b.iter())
39+
.map(|(&x, &y)| (x - y).abs())
40+
.sum::<f32>(),
41+
Similarity::Hamming => a
42+
.iter()
43+
.zip(b.iter())
44+
.map(|(&x, &y)| if (x - y).abs() > 1e-8 { 1f32 } else { 0f32 })
45+
.sum::<f32>(),
5146
Similarity::Cosine => {
52-
let p_score: Vec<f32> = a.iter().zip(b.iter()).map(|(&x, &y)| x * y).collect();
53-
let p = p_score.iter().sum::<f32>();
54-
let q_score: Vec<f32> = a.iter().map(|&n| n * n).collect();
55-
let q = q_score.iter().sum::<f32>().sqrt();
56-
let r_score: Vec<f32> = b.iter().map(|&n| n * n).collect();
57-
let r = r_score.iter().sum::<f32>().sqrt();
58-
1.0 - p / (q * r)
47+
let mut dot = 0.0f32;
48+
let mut norm_a = 0.0f32;
49+
let mut norm_b = 0.0f32;
50+
for (&x, &y) in a.iter().zip(b.iter()) {
51+
dot += x * y;
52+
norm_a += x * x;
53+
norm_b += y * y;
54+
}
55+
1.0 - dot / (norm_a.sqrt() * norm_b.sqrt())
5956
}
6057
}
6158
}

0 commit comments

Comments
 (0)