-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from azizkayumov/develop
reverse knn (preinsert + batchnn)
- Loading branch information
Showing
18 changed files
with
1,427 additions
and
568 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,11 @@ | ||
[workspace] | ||
|
||
members = [ | ||
"lib", | ||
"bench", | ||
"demo", | ||
"lib", | ||
] | ||
resolver = "2" | ||
|
||
[patch.crates-io] | ||
rindex = { path = "lib" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
[package] | ||
name = "bench" | ||
version = "0.1.0" | ||
edition = "2021" | ||
authors = ["Kayumov A.I. <[email protected]>"] | ||
|
||
[dev-dependencies] | ||
rindex = { path = "../lib" } | ||
rand = "0.8.5" | ||
rstar = "0.12.0" | ||
ordered-float = "3.4.0" | ||
criterion = "0.5.1" | ||
|
||
[[bench]] | ||
name = "main" | ||
harness = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
use criterion::{criterion_group, criterion_main}; | ||
mod uniform; | ||
|
||
criterion_group!( | ||
benches, | ||
uniform::build, | ||
uniform::query, | ||
uniform::query_radius | ||
); | ||
criterion_main!(benches); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
use crate::uniform::{DELETION_PROB, DIMENSION as D, K, NUM_OPERATIONS}; | ||
use core::f64; | ||
use criterion::Criterion; | ||
use rand::{rngs::StdRng, Rng, SeedableRng}; | ||
use rindex::Rindex; | ||
use rstar::RTree; | ||
|
||
pub fn benchmark(criterion: &mut Criterion) { | ||
let mut group = criterion.benchmark_group("build"); | ||
//group.sample_size(10); | ||
|
||
group.bench_function("rindex", |b| { | ||
b.iter(|| { | ||
build_rindex(); | ||
}); | ||
}); | ||
|
||
group.bench_function("rstar", |b| { | ||
b.iter(|| { | ||
build_rstar(); | ||
}); | ||
}); | ||
} | ||
|
||
pub fn build_rindex() -> (Rindex<D>, Vec<(usize, [f64; D])>) { | ||
let mut rng = StdRng::seed_from_u64(0); | ||
let mut index = Rindex::new(10, K).expect("Failed to create Rindex"); | ||
let mut points = Vec::new(); | ||
for _ in 0..NUM_OPERATIONS { | ||
let should_delete = rng.gen_bool(DELETION_PROB); | ||
if should_delete && !points.is_empty() { | ||
let idx = rng.gen_range(0..points.len()); | ||
let (point_id, _) = points.swap_remove(idx); | ||
index.delete(point_id); | ||
} else { | ||
let mut point = [0.0; D]; | ||
for i in 0..D { | ||
point[i] = rng.gen_range(-100.0..100.0); | ||
} | ||
let point_id = index.insert(point); | ||
points.push((point_id, point)); | ||
} | ||
} | ||
(index, points) | ||
} | ||
|
||
pub fn build_rstar() -> (RTree<[f64; D]>, Vec<[f64; D]>) { | ||
let mut rng = StdRng::seed_from_u64(0); | ||
let mut rstar = rstar::RTree::new(); | ||
let mut points = Vec::new(); | ||
for _ in 0..NUM_OPERATIONS { | ||
let should_delete = rng.gen_bool(DELETION_PROB); | ||
if should_delete && !points.is_empty() { | ||
let idx = rng.gen_range(0..points.len()); | ||
let point = points.swap_remove(idx); | ||
rstar.remove(&point); | ||
} else { | ||
let mut point = [0.0; D]; | ||
for i in 0..D { | ||
point[i] = rng.gen_range(-100.0..100.0); | ||
} | ||
rstar.insert(point); | ||
points.push(point); | ||
} | ||
} | ||
(rstar, points) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
mod build; | ||
mod query; | ||
mod query_radius; | ||
|
||
// Benchmark parameters: | ||
pub const DIMENSION: usize = 2; | ||
pub const NUM_OPERATIONS: usize = 10000; // Number of operations to perform (insertions and deletions) | ||
pub const DELETION_PROB: f64 = 0.2; // Probability of deleting a point for simulating dynamic data | ||
pub const K: usize = 10; // Number of neighbors to query | ||
pub const RADIUS: f64 = 5.0; // Radius for range queries | ||
pub const RADIUS_SQUARED: f64 = RADIUS * RADIUS; | ||
|
||
pub use build::benchmark as build; | ||
pub use query::benchmark as query; | ||
pub use query_radius::benchmark as query_radius; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
use crate::uniform::build::{build_rindex, build_rstar}; | ||
use crate::uniform::{DIMENSION as D, K}; | ||
use core::f64; | ||
use criterion::Criterion; | ||
use ordered_float::OrderedFloat; | ||
use rindex::Rindex; | ||
use rstar::RTree; | ||
use std::collections::BinaryHeap; | ||
|
||
pub fn benchmark(criterion: &mut Criterion) { | ||
let mut group = criterion.benchmark_group("query"); | ||
//group.sample_size(10); | ||
|
||
let (rindex, pts) = build_rindex(); | ||
group.bench_function("rindex", |b| { | ||
b.iter(|| { | ||
query_rindex(&rindex, &pts); | ||
}); | ||
}); | ||
|
||
let (rstar, pts) = build_rstar(); | ||
group.bench_function("rstar", |b| { | ||
b.iter(|| { | ||
query_rstar(&rstar, &pts); | ||
}); | ||
}); | ||
|
||
group.bench_function("list", |b| { | ||
b.iter(|| { | ||
query_list(&pts); | ||
}); | ||
}); | ||
} | ||
|
||
fn query_rindex(rindex: &Rindex<D>, points: &Vec<(usize, [f64; D])>) { | ||
for (query_id, _) in points { | ||
let (neighbors, _) = rindex.neighbors_of(*query_id); | ||
assert_eq!(neighbors.len(), 10); | ||
} | ||
} | ||
|
||
fn query_rstar(rstar: &RTree<[f64; D]>, points: &Vec<[f64; D]>) { | ||
for query in points { | ||
let mut iter = rstar.nearest_neighbor_iter(&query); | ||
let results = iter.by_ref().take(K).collect::<Vec<_>>(); | ||
assert_eq!(results.len(), K); | ||
} | ||
} | ||
|
||
fn query_list(points: &Vec<[f64; D]>) { | ||
for query in points { | ||
let mut results = BinaryHeap::from(vec![OrderedFloat(f64::INFINITY); K]); | ||
for point in points { | ||
let dist = query | ||
.iter() | ||
.zip(point.iter()) | ||
.map(|(a, b)| (a - b).powi(2)) | ||
.sum::<f64>() | ||
.sqrt(); | ||
if dist < results.peek().unwrap().0 { | ||
results.push(OrderedFloat(dist)); | ||
results.pop(); | ||
} | ||
} | ||
assert_eq!(results.len(), K); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
use crate::uniform::build::{build_rindex, build_rstar}; | ||
use crate::uniform::{DIMENSION as D, RADIUS, RADIUS_SQUARED}; | ||
use core::f64; | ||
use criterion::Criterion; | ||
use rindex::Rindex; | ||
use rstar::RTree; | ||
|
||
pub fn benchmark(criterion: &mut Criterion) { | ||
let mut group = criterion.benchmark_group("query_radius"); | ||
//group.sample_size(10); | ||
|
||
let (rindex, pts) = build_rindex(); | ||
group.bench_function("rindex", |b| { | ||
b.iter(|| { | ||
query_range_rindex(&rindex, &pts); | ||
}); | ||
}); | ||
|
||
let (rstar, pts) = build_rstar(); | ||
group.bench_function("rstar", |b| { | ||
b.iter(|| { | ||
query_range_rstar(&rstar, &pts); | ||
}); | ||
}); | ||
|
||
group.bench_function("list", |b| { | ||
b.iter(|| { | ||
query_range_list(&pts); | ||
}); | ||
}); | ||
} | ||
|
||
fn query_range_rindex(rindex: &Rindex<D>, points: &Vec<(usize, [f64; D])>) { | ||
for (query_id, query) in points { | ||
let (neighbors, _) = rindex.query(&query, RADIUS); | ||
assert!(neighbors.contains(query_id)); | ||
} | ||
} | ||
|
||
fn query_range_rstar(rstar: &RTree<[f64; D]>, points: &Vec<[f64; D]>) { | ||
for query in points { | ||
let result = rstar | ||
.locate_within_distance(*query, RADIUS_SQUARED) | ||
.collect::<Vec<_>>(); | ||
assert!(result.contains(&query)); | ||
} | ||
} | ||
|
||
fn query_range_list(points: &Vec<[f64; D]>) { | ||
for query in points { | ||
let mut results = Vec::new(); | ||
for point in points { | ||
let dist = query | ||
.iter() | ||
.zip(point.iter()) | ||
.map(|(a, b)| (a - b).powi(2)) | ||
.sum::<f64>() | ||
.sqrt(); | ||
if dist <= RADIUS { | ||
results.push(dist); | ||
} | ||
} | ||
assert!(results.contains(&0.0)); | ||
} | ||
} |
Oops, something went wrong.