From f4cd952ccd37ee0eb79977c1242653be93ace88a Mon Sep 17 00:00:00 2001 From: Joe Date: Mon, 20 Oct 2025 15:04:18 -0700 Subject: [PATCH] use forte for fast threadpool --- Cargo.lock | 214 ++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 1 + benches/benchmarks.rs | 3 +- src/lib.rs | 59 +++++------- 4 files changed, 233 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aa2316a..dd9e01e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -53,7 +53,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" dependencies = [ - "windows-sys", + "windows-sys 0.60.2", ] [[package]] @@ -64,7 +64,23 @@ checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys", + "windows-sys 0.60.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "atomic-wait" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55b94919229f2c42292fd71ffa4b75e83193bffdd77b1e858cd55fd2d0b0ea8" +dependencies = [ + "libc", + "windows-sys 0.42.0", ] [[package]] @@ -221,6 +237,18 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "forte" +version = "1.0.0-alpha.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a90f58e1986e49c6ef944f1c94c6bcd06edf7d03711923ddbd26ed3253531771" +dependencies = [ + "async-task", + "atomic-wait", + "tracing", + "tracing-subscriber", +] + [[package]] name = "getrandom" version = "0.3.4" @@ -275,6 +303,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.177" @@ -293,6 +327,15 @@ version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.60.2", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -320,6 +363,12 @@ version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + [[package]] name = "plotters" version = "0.3.7" @@ -532,12 +581,28 @@ dependencies = [ "serde_core", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + [[package]] name = "spacedog" version = "0.1.0" dependencies = [ "clap", "criterion", + "forte", "rand", "rand_hc", ] @@ -559,6 +624,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -569,6 +643,63 @@ dependencies = [ "serde_json", ] +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + [[package]] name = "unicode-ident" version = "1.0.19" @@ -581,6 +712,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "walkdir" version = "2.5.0" @@ -675,7 +812,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys", + "windows-sys 0.60.2", ] [[package]] @@ -684,6 +821,21 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-sys" version = "0.60.2" @@ -700,28 +852,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ "windows-link", - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.53.1" @@ -734,24 +904,48 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.53.1" diff --git a/Cargo.toml b/Cargo.toml index 47aebee..a9c8239 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,5 +14,6 @@ name = "benchmarks" harness = false [dependencies] +forte = "1.0.0-alpha.4" rand = "0.9.2" rand_hc = "0.4.0" diff --git a/benches/benchmarks.rs b/benches/benchmarks.rs index 084706a..f7a81bf 100644 --- a/benches/benchmarks.rs +++ b/benches/benchmarks.rs @@ -85,11 +85,12 @@ fn nearest_short_horizon(c: &mut Criterion) { .collect(); let index = Spindex2d::new(&points).with_horizon(20); + let end = points.len() - 1; let mut i = 0; b.iter(|| { i += 1; - index.nearest(&points[i - 1]).is_some() + index.nearest(&points[(i - 1).min(end)]).is_some() }); }); } diff --git a/src/lib.rs b/src/lib.rs index 0029e85..d87f17a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,7 @@ use std::{collections::HashMap, sync::RwLock, thread}; +static THREAD_POOL: forte::ThreadPool = forte::ThreadPool::new(); + #[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd)] pub struct Point2d { pub x: f64, @@ -63,7 +65,6 @@ impl PVal { } } -#[derive(Debug, Default)] pub struct Spindex2d { pub xs: RwLock>, pub ys: RwLock>, @@ -76,15 +77,17 @@ impl Spindex2d { let mut xs = Vec::with_capacity(len); let mut ys = Vec::with_capacity(len); - thread::scope(|s| { - s.spawn(|| { + THREAD_POOL.populate(); + + THREAD_POOL.scope(|s| { + s.spawn(|_| { for (i, point) in points.iter().enumerate() { let x = PVal::new(i, point.x); xs.push(x); } }); - s.spawn(|| { + s.spawn(|_| { for (i, point) in points.iter().enumerate() { let y = PVal::new(i, point.y); ys.push(y); @@ -112,15 +115,15 @@ impl Spindex2d { /// when constructing this index. May panic if the updated points argument is longer than the /// original points. pub fn update(&self, points: &[Point2d]) { - thread::scope(|s| { - s.spawn(|| { + THREAD_POOL.scope(|s| { + s.spawn(|_| { let mut xs = self.xs.write().unwrap(); for point in xs.iter_mut() { point.val = points[point.point_index].x; } }); - s.spawn(|| { + s.spawn(|_| { let mut ys = self.ys.write().unwrap(); for point in ys.iter_mut() { point.val = points[point.point_index].y; @@ -144,13 +147,13 @@ impl Spindex2d { /// Search an axis-aligned bounding box whose sides are `span` away from the given point. pub fn aabb(&self, point: &Point2d, span: f64) -> Vec { let span = span / 2.0; + let sz = { self.xs.read().unwrap().len() / 2 }; + let mut nxs = HashMap::with_capacity(sz); + let mut nys = HashMap::with_capacity(sz); - let mut nxs = HashMap::new(); - let mut nys = HashMap::new(); - - thread::scope(|s| { + THREAD_POOL.scope(|s| { // x axis - s.spawn(|| { + s.spawn(|_| { let xs = self.xs.read().unwrap(); let p = PVal::new(0, point.x); let nx = match xs.binary_search(&p) { @@ -159,19 +162,14 @@ impl Spindex2d { let mut i = nx; // first walk backwards - loop { + while i > 0 { + i -= 1; let p = xs[i]; // `p.val` is less than `point.x` because the xs are sorted let dist = point.x - p.val(); if dist <= span { nxs.insert(p.point_index(), p.val()); - } else { - break; } - if i == 0 { - break; - } - i -= 1; } // now forwards @@ -189,7 +187,7 @@ impl Spindex2d { }); // y axis - s.spawn(|| { + s.spawn(|_| { let ys = self.ys.read().unwrap(); let p = PVal::new(0, point.y); let ny = match ys.binary_search(&p) { @@ -197,19 +195,14 @@ impl Spindex2d { }; let mut i = ny; // backwards - loop { + while i > 0 { + i -= 1; let p = ys[i]; // `p.val` is less than `point.y` because the ys are sorted let dist = point.y - p.val(); if dist <= span { nys.insert(p.point_index(), p.val()); - } else { - break; } - if i == 0 { - break; - } - i -= 1; } // forwards @@ -240,8 +233,8 @@ impl Spindex2d { let horizon = self.horizon; let mut nxs = HashMap::with_capacity(horizon * 2); let mut nys = HashMap::with_capacity(horizon * 2); - thread::scope(|s| { - s.spawn(|| { + THREAD_POOL.scope(|s| { + s.spawn(|_| { let xs = self.xs.read().unwrap(); let p = PVal::new(0, point.x); let nx = match xs.binary_search(&p) { @@ -254,7 +247,7 @@ impl Spindex2d { } }); - s.spawn(|| { + s.spawn(|_| { let ys = self.ys.read().unwrap(); let p = PVal::new(0, point.y); let ny = match ys.binary_search(&p) { @@ -297,13 +290,13 @@ impl Spindex2d { } fn sort(&self) { - thread::scope(|s| { - s.spawn(|| { + THREAD_POOL.scope(|s| { + s.spawn(|_| { let mut xs = self.xs.write().unwrap(); xs.sort_unstable(); }); - s.spawn(|| { + s.spawn(|_| { let mut ys = self.ys.write().unwrap(); ys.sort_unstable(); });