2x faster than rtree
This commit is contained in:
parent
36c1a64e54
commit
4ca8e55dab
1 changed files with 60 additions and 57 deletions
|
@ -1,5 +1,8 @@
|
||||||
use std::{
|
use std::{
|
||||||
sync::{Arc, RwLock},
|
sync::{
|
||||||
|
atomic::{AtomicU64, AtomicUsize, Ordering::Relaxed},
|
||||||
|
Arc, RwLock,
|
||||||
|
},
|
||||||
thread,
|
thread,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,21 +11,15 @@ struct Point2d {
|
||||||
y: f64,
|
y: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Default)]
|
||||||
struct PointRef2d {
|
|
||||||
x: usize,
|
|
||||||
y: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy)]
|
|
||||||
struct PVal {
|
struct PVal {
|
||||||
point: usize,
|
point: usize,
|
||||||
val: f64,
|
val: AtomicU64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for PVal {
|
impl PartialEq for PVal {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.val == other.val
|
self.val.load(Relaxed) == other.val.load(Relaxed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +27,9 @@ impl Eq for PVal {}
|
||||||
|
|
||||||
impl PartialOrd for PVal {
|
impl PartialOrd for PVal {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
self.val.partial_cmp(&other.val)
|
let a = f64::from_bits(self.val.load(Relaxed));
|
||||||
|
let b = f64::from_bits(other.val.load(Relaxed));
|
||||||
|
a.partial_cmp(&b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,33 +40,37 @@ impl Ord for PVal {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Spindex2d {
|
struct Spindex2d {
|
||||||
points: Arc<Vec<RwLock<PointRef2d>>>,
|
xpoints: Arc<Vec<AtomicUsize>>,
|
||||||
xs: Arc<RwLock<Vec<RwLock<PVal>>>>,
|
ypoints: Arc<Vec<AtomicUsize>>,
|
||||||
ys: Arc<RwLock<Vec<RwLock<PVal>>>>,
|
xs: Arc<RwLock<Vec<PVal>>>,
|
||||||
|
ys: Arc<RwLock<Vec<PVal>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Spindex2d {
|
impl Spindex2d {
|
||||||
pub fn new(points: &[Point2d]) -> Self {
|
pub fn new(points: &[Point2d]) -> Self {
|
||||||
let mut ps = Vec::with_capacity(points.len());
|
let mut xpoints = Vec::with_capacity(points.len());
|
||||||
|
let mut ypoints = Vec::with_capacity(points.len());
|
||||||
let mut xs = Vec::with_capacity(points.len());
|
let mut xs = Vec::with_capacity(points.len());
|
||||||
let mut ys = Vec::with_capacity(points.len());
|
let mut ys = Vec::with_capacity(points.len());
|
||||||
for (i, point) in points.iter().enumerate() {
|
for (i, point) in points.iter().enumerate() {
|
||||||
let x = PVal {
|
let x = PVal {
|
||||||
point: i,
|
point: i,
|
||||||
val: point.x,
|
val: AtomicU64::new(point.x.to_bits()),
|
||||||
};
|
};
|
||||||
xs.push(x.into());
|
xs.push(x);
|
||||||
let y = PVal {
|
let y = PVal {
|
||||||
point: i,
|
point: i,
|
||||||
val: point.y,
|
val: AtomicU64::new(point.y.to_bits()),
|
||||||
};
|
};
|
||||||
ys.push(y.into());
|
ys.push(y);
|
||||||
let p = PointRef2d { x: i, y: i };
|
|
||||||
ps.push(p.into());
|
xpoints.push(AtomicUsize::new(i));
|
||||||
|
ypoints.push(AtomicUsize::new(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
let index = Self {
|
let index = Self {
|
||||||
points: ps.into(),
|
xpoints: xpoints.into(),
|
||||||
|
ypoints: ypoints.into(),
|
||||||
xs: Arc::new(RwLock::new(xs)),
|
xs: Arc::new(RwLock::new(xs)),
|
||||||
ys: Arc::new(RwLock::new(ys)),
|
ys: Arc::new(RwLock::new(ys)),
|
||||||
};
|
};
|
||||||
|
@ -81,53 +84,48 @@ impl Spindex2d {
|
||||||
/// when constructing this index. May panic if the updated points argument is longer than the
|
/// when constructing this index. May panic if the updated points argument is longer than the
|
||||||
/// original points.
|
/// original points.
|
||||||
pub fn update(&self, points: &[Point2d]) {
|
pub fn update(&self, points: &[Point2d]) {
|
||||||
todo!()
|
let mut xs = self.xs.write().unwrap();
|
||||||
|
let mut ys = self.ys.write().unwrap();
|
||||||
|
for (i, point) in points.iter().enumerate() {
|
||||||
|
let xi = self.xpoints[i].load(Relaxed);
|
||||||
|
let yi = self.ypoints[i].load(Relaxed);
|
||||||
|
let x = point.x.to_bits();
|
||||||
|
let x = PVal {
|
||||||
|
point: i,
|
||||||
|
val: x.into(),
|
||||||
|
};
|
||||||
|
xs[xi] = x;
|
||||||
|
|
||||||
|
let y = point.y.to_bits();
|
||||||
|
let y = PVal {
|
||||||
|
point: i,
|
||||||
|
val: y.into(),
|
||||||
|
};
|
||||||
|
ys[yi] = y;
|
||||||
|
}
|
||||||
|
self.sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sort(&self) {
|
fn sort(&self) {
|
||||||
let xs = self.xs.clone();
|
let xs = self.xs.clone();
|
||||||
|
let points = self.xpoints.clone();
|
||||||
let xhandle = thread::spawn(move || {
|
let xhandle = thread::spawn(move || {
|
||||||
let mut xs = xs.write().unwrap();
|
let mut xs = xs.write().unwrap();
|
||||||
xs.sort_unstable_by(|a, b| {
|
xs.sort_unstable();
|
||||||
let a = a.read().unwrap();
|
|
||||||
let b = b.read().unwrap();
|
|
||||||
a.cmp(&b)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
let ys = self.ys.clone();
|
|
||||||
let yhandle = thread::spawn(move || {
|
|
||||||
let mut ys = ys.write().unwrap();
|
|
||||||
ys.sort_unstable_by(|a, b| {
|
|
||||||
let a = a.read().unwrap();
|
|
||||||
let b = b.read().unwrap();
|
|
||||||
a.cmp(&b)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
xhandle.join().unwrap();
|
|
||||||
yhandle.join().unwrap();
|
|
||||||
|
|
||||||
let xs = self.xs.clone();
|
|
||||||
let points = self.points.clone();
|
|
||||||
let xhandle = thread::spawn(move || {
|
|
||||||
let xs = xs.read().unwrap();
|
|
||||||
for (i, x) in xs.iter().enumerate() {
|
for (i, x) in xs.iter().enumerate() {
|
||||||
let x = x.read().unwrap();
|
|
||||||
let p = x.point;
|
let p = x.point;
|
||||||
points[p].write().unwrap().x = i;
|
points[p].store(i, Relaxed);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let ys = self.ys.clone();
|
let ys = self.ys.clone();
|
||||||
let points = self.points.clone();
|
let points = self.ypoints.clone();
|
||||||
let yhandle = thread::spawn(move || {
|
let yhandle = thread::spawn(move || {
|
||||||
let ys = ys.read().unwrap();
|
let mut ys = ys.write().unwrap();
|
||||||
|
ys.sort_unstable();
|
||||||
for (i, y) in ys.iter().enumerate() {
|
for (i, y) in ys.iter().enumerate() {
|
||||||
let y = y.read().unwrap();
|
|
||||||
let p = y.point;
|
let p = y.point;
|
||||||
points[p].write().unwrap().y = i;
|
points[p].store(i, Relaxed);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -185,11 +183,16 @@ fn update_positions(c: &mut Criterion) {
|
||||||
|
|
||||||
let index = Spindex2d::new(&points);
|
let index = Spindex2d::new(&points);
|
||||||
let mut round = 0;
|
let mut round = 0;
|
||||||
b.iter(|| todo!());
|
b.iter(|| {
|
||||||
|
if round % 2 == 0 {
|
||||||
|
index.update(&jitters);
|
||||||
|
} else {
|
||||||
|
index.update(&points);
|
||||||
|
}
|
||||||
|
round += 1;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//fn reuse_index(_c: &mut Criterion) {}
|
|
||||||
|
|
||||||
criterion_group!(benches, new_index);
|
criterion_group!(benches, new_index);
|
||||||
criterion_main!(benches);
|
criterion_main!(benches);
|
||||||
|
|
Loading…
Reference in a new issue