add multithreading for seed cracking
All checks were successful
Build / build (push) Successful in 1m55s

This commit is contained in:
2025-06-24 20:59:32 +02:00
parent 2c2bfd3489
commit f0156ccec4
3 changed files with 51 additions and 11 deletions

1
Cargo.lock generated
View File

@ -224,6 +224,7 @@ dependencies = [
"lru", "lru",
"memmap2", "memmap2",
"rand 0.9.1", "rand 0.9.1",
"rayon",
"serde", "serde",
"serde_json", "serde_json",
"sqlx", "sqlx",

View File

@ -55,6 +55,7 @@ memmap2 = "0.9.5"
bytemuck = "1.23.1" bytemuck = "1.23.1"
flame = "0.2.2" flame = "0.2.2"
flamer = "0.5.0" flamer = "0.5.0"
rayon = "1.10.0"
[dev-dependencies] [dev-dependencies]
criterion = "0.5" criterion = "0.5"

View File

@ -1,4 +1,13 @@
use std::{fs::File, path::PathBuf, sync::LazyLock, time::Instant}; use std::{
cell::RefCell,
fs::File,
path::PathBuf,
sync::{
LazyLock,
atomic::{AtomicU32, Ordering},
},
time::Instant,
};
use az::{Az, WrappingAs}; use az::{Az, WrappingAs};
use battlesnake::types::{Coord, Direction, wire::Request}; use battlesnake::types::{Coord, Direction, wire::Request};
@ -8,6 +17,7 @@ use clap::Parser;
use hashbrown::HashMap; use hashbrown::HashMap;
use log::{debug, error, info, trace}; use log::{debug, error, info, trace};
use memmap2::{Mmap, MmapOptions}; use memmap2::{Mmap, MmapOptions};
use rayon::iter::{IntoParallelIterator, ParallelIterator};
type DynError = Box<dyn std::error::Error>; type DynError = Box<dyn std::error::Error>;
@ -21,6 +31,9 @@ struct Args {
#[arg()] #[arg()]
/// The file to read the requests from /// The file to read the requests from
file: PathBuf, file: PathBuf,
/// Use multiple cores to speed up search
#[arg(long, short)]
parallel: bool,
} }
//#[flame] //#[flame]
@ -65,18 +78,43 @@ fn main() -> Result<(), DynError> {
} else { } else {
info!("Trying every seed from 1 to {}", i32::MAX); info!("Trying every seed from 1 to {}", i32::MAX);
let start = Instant::now(); let start = Instant::now();
for seed in 1..i32::MAX { if args.parallel {
if seed % 1_000_000 == 0 { thread_local! {
debug!("Checking {seed:>10}"); static RAND: RefCell<SeedRand> = RefCell::new(SeedRand::new(0));
} }
if prepared.validate(&mut rand, i64::from(seed), false) { let tried = AtomicU32::new(0);
let elapsed = start.elapsed(); let seed = (1..i32::MAX).into_par_iter().find_any(|seed| {
info!( tried.fetch_add(1, Ordering::Relaxed);
"Trying {seed} seeds took {elapsed:?} ({:?} / seed)", RAND.with_borrow_mut(|rand| prepared.validate(rand, i64::from(*seed), false))
elapsed / seed.az() });
); let elapsed = start.elapsed();
let tried = tried.load(Ordering::Relaxed);
info!(
"Trying {tried} seeds took {elapsed:?} ({:?} / seed)",
elapsed / tried.az()
);
if let Some(seed) = seed {
println!("The correct seed is {seed}"); println!("The correct seed is {seed}");
break; } else {
println!("No valid seed found");
}
} else {
let seed = (1..i32::MAX).find(|seed| {
if seed % 1_000_000 == 0 {
debug!("Checking {seed:>10}");
}
prepared.validate(&mut rand, i64::from(*seed), false)
});
let elapsed = start.elapsed();
let tried = seed.unwrap_or(i32::MAX);
info!(
"Trying {tried} seeds took {elapsed:?} ({:?} / seed)",
elapsed / tried.az()
);
if let Some(seed) = seed {
println!("The correct seed is {seed}");
} else {
println!("No valid seed found");
} }
} }
} }