Compare commits

..

No commits in common. "multithread" and "main" have entirely different histories.

4 changed files with 9 additions and 90 deletions

20
Cargo.lock generated
View File

@ -2,24 +2,6 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]] [[package]]
name = "hcn" name = "hcn"
version = "1.0.0-multithread" version = "1.0.0"
dependencies = [
"itertools",
]
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]

View File

@ -1,10 +1,9 @@
[package] [package]
name = "hcn" name = "hcn"
version = "1.0.0-multithread" version = "1.0.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
itertools = "0.13"
[lints.rust] [lints.rust]
unsafe_code = "forbid" unsafe_code = "forbid"

View File

@ -1,14 +1,7 @@
mod sieve; mod sieve;
use std::{ use std::time::Instant;
collections::HashMap,
env,
sync::Arc,
thread::{self, available_parallelism},
time::Instant,
};
use itertools::Itertools as _;
use sieve::get_primes; use sieve::get_primes;
const MAX_SIEVED_PRIMES: usize = 100_000_000; const MAX_SIEVED_PRIMES: usize = 100_000_000;
@ -51,76 +44,21 @@ fn prime_factors(nr: u64, primes: &[u64]) -> u64 {
num_teilers num_teilers
} }
fn the_thread(mut start: u64, end: u64, primes: &[u64]) -> HashMap<u64, u64> {
let mut max_teilers = 0;
let mut max_teilers_hashmap = HashMap::new();
let mut step_size = 10;
if start == 0 {
start = 2;
step_size = 2;
}
for nr in (start..=end).step_by(step_size) {
let teilers = prime_factors(nr, primes);
if teilers > max_teilers {
max_teilers = teilers;
max_teilers_hashmap.insert(nr, teilers);
}
}
max_teilers_hashmap
}
fn calculate_chunk_bounds(i: usize, num_threads: usize, max_nr: usize) -> (usize, usize) {
let chunk_size = max_nr / num_threads;
let start = i * chunk_size;
let end = ((i + 1) * chunk_size).min(max_nr);
(start, end)
}
fn main() { fn main() {
let max_nr = env::args()
.nth(1)
.expect("Usage: hcn <max_nr>")
.parse::<usize>()
.expect("Invalid max_nr");
let start = Instant::now(); let start = Instant::now();
println!("Precalculating primes..."); println!("Precalculating primes...");
let primes = get_primes(MAX_SIEVED_PRIMES); let primes = get_primes(MAX_SIEVED_PRIMES);
println!("{} primes. Took {:?}", primes.len(), start.elapsed()); println!("{} primes. Took {:?}", primes.len(), start.elapsed());
let primes = Arc::new(primes);
#[allow(clippy::unwrap_used)]
let num_threads = available_parallelism().unwrap().get();
let mut threads = Vec::with_capacity(num_threads);
let now = Instant::now();
for i in 0..num_threads {
let (start, end) = calculate_chunk_bounds(i, num_threads, max_nr);
let primes = primes.clone();
threads.push(thread::spawn(move || {
the_thread(start as u64, end as u64, &primes)
}));
}
let mut results = HashMap::new();
for thread in threads {
let thread_result = thread.join().expect("Thread failed to join (panicked?)");
results.extend(thread_result);
}
let mut max_teilers = 0; let mut max_teilers = 0;
for (nr, teilers) in results.into_iter().sorted() { let start = Instant::now();
for nr in (2..1_000_000_000).step_by(2) {
let teilers = prime_factors(nr, &primes);
if teilers > max_teilers { if teilers > max_teilers {
println!("{nr}: {teilers}"); println!("{nr}: {teilers} ({:?} since start)", start.elapsed());
max_teilers = teilers; max_teilers = teilers;
} }
} }
println!("Took {:?}", now.elapsed());
} }

View File

@ -29,7 +29,7 @@ fn find_next_prime(nr: &mut u64, sieve: &mut [bool]) -> Option<u64> {
.iter() .iter()
.enumerate() .enumerate()
.skip(start_idx) .skip(start_idx)
.find(|(_, &is_prime)| is_prime) .find(|&(_, &is_prime)| is_prime)
{ {
*nr = idx as u64; *nr = idx as u64;
return Some(*nr); return Some(*nr);