From 5d2ff3712b6d3a978cf207e3a2476db052801adf Mon Sep 17 00:00:00 2001 From: b1ek Date: Wed, 2 Aug 2023 23:29:06 +1000 Subject: [PATCH] better practice for callback in POWSolver.solve_blocking --- examples/multithreaded/Cargo.lock | 132 +++++++++++++++++++++++++++++ examples/multithreaded/Cargo.toml | 1 + examples/multithreaded/src/main.rs | 21 ++++- src/solver.rs | 60 ++++++++----- 4 files changed, 191 insertions(+), 23 deletions(-) diff --git a/examples/multithreaded/Cargo.lock b/examples/multithreaded/Cargo.lock index 9e59803..8a91c3c 100644 --- a/examples/multithreaded/Cargo.lock +++ b/examples/multithreaded/Cargo.lock @@ -33,6 +33,19 @@ dependencies = [ "inout", ] +[[package]] +name = "console" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys", +] + [[package]] name = "cpufeatures" version = "0.2.9" @@ -63,6 +76,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "generic-array" version = "0.14.7" @@ -93,6 +112,19 @@ dependencies = [ "digest", ] +[[package]] +name = "indicatif" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ff8cc23a7393a397ed1d7f56e6365cba772aba9f9912ab968b03043c395d057" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + [[package]] name = "inout" version = "0.1.3" @@ -102,12 +134,33 @@ dependencies = [ "generic-array", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "password-hash" version = "0.5.0" @@ -129,6 +182,12 @@ dependencies = [ "hmac", ] +[[package]] +name = "portable-atomic" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f32154ba0af3a075eefa1eda8bb414ee928f62303a54ea85b8d6638ff1a6ee9e" + [[package]] name = "powlib" version = "0.1.0" @@ -141,6 +200,7 @@ dependencies = [ name = "powlib-multithreaded-example" version = "0.0.1" dependencies = [ + "indicatif", "powlib", ] @@ -224,6 +284,12 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + [[package]] name = "version_check" version = "0.9.4" @@ -235,3 +301,69 @@ name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[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_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[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_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[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_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" diff --git a/examples/multithreaded/Cargo.toml b/examples/multithreaded/Cargo.toml index 0bf2017..7c7a73f 100644 --- a/examples/multithreaded/Cargo.toml +++ b/examples/multithreaded/Cargo.toml @@ -5,4 +5,5 @@ edition = "2021" publish = false [dependencies] +indicatif = "0.17.5" powlib = { path = '../..' } diff --git a/examples/multithreaded/src/main.rs b/examples/multithreaded/src/main.rs index 84ffb51..5c5d2a6 100644 --- a/examples/multithreaded/src/main.rs +++ b/examples/multithreaded/src/main.rs @@ -1,8 +1,25 @@ +use std::time::Instant; + +use indicatif::ProgressBar; use powlib::{gen::{POWRange, POWChallenge}, solver::POWSolver}; fn main() { - let challenge = POWChallenge::make(POWRange::new(0, 20480)); + let challenge = POWChallenge::make(POWRange::new(0, 204800)); let mut solver = POWSolver::new(challenge); - println!("Found {} with 8 threads", solver.solve_blocking(8, Some(|x| println!("{x}")))); + let mut count = 0; + + let progess = ProgressBar::new(204800); + let thr_progress = progess.clone(); + + let time = Instant::now(); + + let result = solver.solve_blocking(16, Some(move |_| { + thr_progress.set_position(count); + count += 1; + })); + + progess.finish(); + + println!("Found {result} in {} ms", time.elapsed().as_secs_f32()); } \ No newline at end of file diff --git a/src/solver.rs b/src/solver.rs index e0ada28..461c6c4 100644 --- a/src/solver.rs +++ b/src/solver.rs @@ -1,4 +1,4 @@ -use std::{sync::{mpsc, Arc, atomic::{AtomicBool, Ordering}}, thread::{self, JoinHandle}}; +use std::{sync::{mpsc, Arc, atomic::{AtomicBool, Ordering}}, thread::{self, JoinHandle}, time::Duration}; use crate::{gen::POWChallenge, num::Num}; @@ -8,6 +8,11 @@ pub struct POWSolver { result: Option } +enum SolverThreadMessage { + PlainNumber(u128), + Found(u128) +} + impl POWSolver { /** @@ -74,8 +79,8 @@ impl POWSolver { This method also supports callbacks via `Option` */ - pub fn solve_blocking(self: &mut POWSolver, threads: u8, callback: Option) -> u128 { - let (send, recv) = mpsc::sync_channel::(1); + pub fn solve_blocking(self: &mut POWSolver, threads: u8, mut callback: Option) -> u128 { + let (send, recv) = mpsc::sync_channel::(1); let mut thread_start: u128 = self.challenge.range.min; let size = self.chunksize(threads); @@ -94,36 +99,49 @@ impl POWSolver { } handles.push( - thread::spawn(move || { - for j in thread_start..end { - if stop.load(Ordering::Relaxed) { break } - if callback.is_some() { - callback.unwrap()(j); - } + thread::spawn(move || { + for j in thread_start..end { + if stop.load(Ordering::Relaxed) { break } - if solver.challenge.check(Num::from(j as u128)) { - stop.store(true, Ordering::Relaxed); - send.send(j as u128).unwrap(); - } + if solver.challenge.check(Num::from(j as u128)) { + stop.store(true, Ordering::Relaxed); + send.send(SolverThreadMessage::Found(j)).unwrap(); + } else { + send.send(SolverThreadMessage::PlainNumber(j)).unwrap(); } } - ) + }) ); thread_start = thread_start + size + 1; } - let result = recv.recv().unwrap(); - stop.load(Ordering::Relaxed); + let mut result = 0; loop { - let mut all_finished = true; - for handle in handles.iter() { - if !handle.is_finished() { - all_finished = false + let status = recv.recv().unwrap(); + match status { + SolverThreadMessage::PlainNumber(num) => { + if callback.is_some() { + callback.as_mut().unwrap()(num); + } + }, + SolverThreadMessage::Found(num) => { + result = num; + stop.store(true, Ordering::Relaxed); + break; } } - if all_finished { break } + + if stop.load(Ordering::Relaxed) { + let mut all_finished = true; + for handle in handles.iter() { + if !handle.is_finished() { + all_finished = false + } + } + if all_finished { break } + } } self.result = Some(result);