From c607c3949f1e520da4afd696c4e2891dec6ef2b2 Mon Sep 17 00:00:00 2001 From: Mystikfluu Date: Mon, 27 Feb 2023 20:43:55 +0100 Subject: [PATCH] better multithread --- Cargo.lock | 56 ++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/is_prime.rs | 34 ++++++++++++++--------- src/main.rs | 71 ++++++++++++++++++++++++++++++++++++------------- 4 files changed, 130 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68fb11b..52c80f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,11 +8,33 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "isprime" version = "0.1.0" dependencies = [ "num-bigint", + "thread-priority", +] + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", ] [[package]] @@ -44,3 +66,37 @@ checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] + +[[package]] +name = "thread-priority" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978519ae4c6891352f964b88da4ab5a3a9b74a40247cda5baee145dae6cd3b71" +dependencies = [ + "cfg-if", + "libc", + "log", + "winapi", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 9b9b39e..805d545 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] num-bigint = { default-features = false, version = "0.4.3" } +thread-priority = "0.10.0" [profile.release] lto = true # Enable link-time optimization diff --git a/src/is_prime.rs b/src/is_prime.rs index 0629f2b..1fa15bf 100644 --- a/src/is_prime.rs +++ b/src/is_prime.rs @@ -1,21 +1,13 @@ -use num_bigint::BigUint; -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct PrimeUtils { - //prime_cache: Vec -} -impl PrimeUtils { +pub mod prime_utils { + use num_bigint::BigUint; - pub fn new() -> Self { - Self { } - } - - pub fn log_2(self: &Self, x: BigUint) -> u64 { + pub fn log_2(x: BigUint) -> u64 { x.bits() - 1 } - pub fn is_prime(self: &Self, number: &BigUint) -> bool { + pub fn is_prime(number: &BigUint, g_primes: &Vec) -> bool { if BigUint::from(1u8) == *number { return false; } @@ -31,7 +23,7 @@ impl PrimeUtils { // number = 2^a - 1 // a = log2(number + 1) - let a = self.log_2(number+1u8); + let a = log_2(number+1u8); if BigUint::from(2u8).pow(a as u32)-BigUint::from(1u8) != *number { let mut i = BigUint::from(1u8); let one = BigUint::from(1u8); @@ -39,6 +31,22 @@ impl PrimeUtils { let sqrtnum = number.sqrt()+&one; //fake ceil function let mut is_prime = true; + + match g_primes.iter().max() { + Some(max_value) => { + if max_value > &sqrtnum { + for prime in g_primes { + if prime<&sqrtnum { + if number%prime == zero { + return false; + } + } + } + } + }, + None => {} + }; + loop { i = i + &one; if number%&i == zero { diff --git a/src/main.rs b/src/main.rs index 9757235..3ff7f62 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,8 @@ pub mod is_prime; use std::{time::SystemTime,thread}; use num_bigint::BigUint; -use crate::is_prime::PrimeUtils; +use crate::is_prime::prime_utils; +use thread_priority::{set_current_thread_priority,ThreadPriority}; fn p(n: f64) -> f64 { let ln_n = n.ln(); @@ -19,6 +20,9 @@ fn p(n: f64) -> f64 { fn main() { + + assert!(set_current_thread_priority(ThreadPriority::Max).is_ok()); + /* let mut buffer = String::new(); let stdin = io::stdin(); @@ -38,34 +42,61 @@ fn main() { let sys_time = SystemTime::now(); - let utils = PrimeUtils::new(); - - let n:f64 = 1_000f64; - let nthprime_approx = p(n*1.01) as u128; + let n:f64 = 1_000_000f64; + let nthprime_approx = p(n*1.02) as u128; const THREADS: u128 = 12; let workloads = nthprime_approx/THREADS; - let mut primes: Vec = vec![]; + let primecache: Vec = vec![]; + let primemutex = std::sync::Mutex::new(primecache); + let primearc = std::sync::Arc::new(primemutex); let mut joins = vec![]; for i in 0..THREADS { + let arcclone = primearc.clone(); let tprimes = thread::spawn(move || { - let mut lprimes = vec![]; + + assert!(set_current_thread_priority(ThreadPriority::Max).is_ok()); + + let one_thousand = &BigUint::from(1_000u16); + let one_hundred = &BigUint::from(100u8); + let ten = &BigUint::from(10u8); + + let work_uint = BigUint::from(workloads); let mut number = BigUint::from(i)*&work_uint; let inc = BigUint::from(1u8); + // let zero = BigUint::from(0u8); let max = BigUint::from(i+1)*work_uint; - + let mut primecache = vec![]; loop { number = number + &inc; - if utils.is_prime(&number) { - lprimes.push(number.clone()); + + if prime_utils::is_prime(&number,&mut primecache) { + primecache.push(number.clone()); + //println!("Found a prime {} {}",number, primecache.len()); + } + if (&number * one_thousand)/&max/ten == &number/&max*one_hundred { + let mut new_primecache = arcclone.lock().unwrap(); + new_primecache.append(&mut primecache); + new_primecache.sort(); + new_primecache.dedup(); + + primecache = new_primecache.clone(); + } if number == max { break; } - } - lprimes + } + + let mut new_primecache = arcclone.lock().unwrap(); + new_primecache.append(&mut primecache); + drop(primecache); + new_primecache.sort(); + new_primecache.dedup(); + + true }); joins.push(tprimes); } @@ -74,10 +105,7 @@ fn main() { let mut njoins = vec![]; for join in joins { if join.is_finished() { - let tp = join.join(); - if let Ok(mut tprimes) = tp { - primes.append(&mut tprimes); - } + join.join().unwrap(); } else { njoins.push(join); } @@ -87,20 +115,25 @@ fn main() { break; } } + + let mut primes = primearc.lock().unwrap().to_vec(); + let removed = (primes.len()-n as usize).clamp(0, primes.len()); if removed != 0 { + println!("removing {removed} primes"); for _ in 0..removed { primes.pop(); } } - let added = (n as usize-primes.len()).clamp(0, n as usize); + let added = n as usize-primes.len(); if primes.len() < n as usize { + println!("Less primes than expected!"); let mut number = BigUint::from(THREADS)*BigUint::from(workloads); let inc = BigUint::from(1u8); loop { number = number + &inc; - if utils.is_prime(&number) { + if prime_utils::is_prime(&number, &primes) { primes.push(number.clone()); } if primes.len() == n as usize { @@ -115,7 +148,7 @@ fn main() { println!("{:?}", primes); - println!("prime count: {}, expected: {}, primes added: {} | {}%",primes.len(),n,added,(added as f64)/primes.len() as f64*100.0); + println!("prime count: {}, expected: {}, primes added: {} | {}%, removed: {}",primes.len(),n,added,(added as f64)/primes.len() as f64*100.0, removed); println!("last prime approx: {}",nthprime_approx); println!("And that's time: {difference:?}");