better multithread

This commit is contained in:
Mystikfluu 2023-02-27 20:43:55 +01:00
parent c359ca292a
commit c607c3949f
4 changed files with 130 additions and 32 deletions

56
Cargo.lock generated
View File

@ -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"

View File

@ -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

View File

@ -1,21 +1,13 @@
use num_bigint::BigUint;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct PrimeUtils {
//prime_cache: Vec<BigUint>
}
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<BigUint>) -> 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 {

View File

@ -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<BigUint> = vec![];
let primecache: Vec<BigUint> = 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:?}");