Browse Source

added multithreading for dataset creation subcommand

master
Thomas Johnson 6 months ago
parent
commit
dabb69df3e
  1. 79
      src/main.rs

79
src/main.rs

@ -50,6 +50,7 @@ enum Op {
},
RandomHist {
samples: usize,
threads: usize,
wrapx: usize,
wrapy: usize,
maxsteps: usize,
@ -63,6 +64,7 @@ const USAGE_STRING: &str =
fn main()
{
use std::sync::{mpsc, atomic::AtomicUsize, Arc};
let mut args = std::env::args().skip(1);
let mut ops = vec![];
loop {
@ -91,6 +93,7 @@ fn main()
Some("randhist") => {
ops.push(Op::RandomHist {
samples: args.next().expect("incorrect usage").parse::<usize>().expect("not an integer"),
threads: args.next().expect("incorrect usage").parse::<usize>().expect("not an integer"),
wrapx: args.next().expect("incorrect usage").parse::<usize>().expect("not an integer"),
wrapy: args.next().expect("incorrect usage").parse::<usize>().expect("not an integer"),
maxsteps: args.next().expect("incorrect usage").parse::<usize>().expect("not an integer"),
@ -108,7 +111,6 @@ fn main()
None => break
}
}
println!("ops: {:?}", ops);
for op in ops.iter_mut() {
match op {
Op::FromFile { filename, init_grid, wrapx, wrapy, .. } => {
@ -147,8 +149,8 @@ fn main()
Op::FromFile {
filename: _,
init_grid: Some(mut init_grid),
wrapx,
wrapy,
wrapx: _,
wrapy: _,
maxsteps,
rules: (on, off),
delay_ms,
@ -247,6 +249,7 @@ fn main()
},
Op::RandomHist {
samples,
threads,
wrapx,
wrapy,
maxsteps,
@ -254,40 +257,56 @@ fn main()
} => {
let wrapx = NonZeroUsize::new(wrapx).unwrap();
let wrapy = NonZeroUsize::new(wrapy).unwrap();
let mut rng = rand::thread_rng();
for _ in 0..samples {
let prob = rng.gen::<f64>();
let mut init_grid = Grid::new_random(wrapx, wrapy, prob);
let fo = find_first_oscillation(&mut init_grid, &on, &off, maxsteps);
if let Some((stability_time, period)) = fo {
let mut count_off = 0;
let mut count_on = 0;
init_grid.per_tile(|_, t|
{
for x in 0 .. TILESIZE
{
for y in 0 .. TILESIZE
let (tx, rx) = mpsc::channel();
let i = Arc::new(AtomicUsize::new(0));
for _ in 0..threads {
let tx = tx.clone();
let i = i.clone();
let f = move || {
let mut rng = rand::thread_rng();
while i.fetch_add(1, std::sync::atomic::Ordering::Relaxed) < samples {
let prob = rng.gen::<f64>();
let mut init_grid = Grid::new_random(wrapx, wrapy, prob);
let fo = find_first_oscillation(&mut init_grid, &on, &off, maxsteps);
if let Some((stability_time, period)) = fo {
let mut count_off = 0;
let mut count_on = 0;
init_grid.per_tile(|_, t|
{
match t.get_at(x, y)
for x in 0 .. TILESIZE
{
State::Dead => { count_off += 1; },
State::Alive => { count_on += 1; },
for y in 0 .. TILESIZE
{
match t.get_at(x, y)
{
State::Dead => { count_off += 1; },
State::Alive => { count_on += 1; },
}
}
}
}
}
});
let ratio = if count_off + count_on != 0 {
(count_on as f64) / (count_off + count_on) as f64
} else {
0.0
};
});
let ratio = if count_off + count_on != 0 {
(count_on as f64) / (count_off + count_on) as f64
} else {
0.0
};
tx.send((prob, Some((stability_time, period, count_off, count_on, ratio)))).expect("main thread ended before child");
} else {
tx.send((prob, None)).expect("main thread ended before child");
};
}
};
std::thread::spawn(f);
}
std::mem::drop(tx);
while let Ok((prob, stats)) = rx.recv() {
if let Some((stability_time, period, count_off, count_on, ratio)) = stats {
println!("{wrapx} {wrapy} {prob} {stability_time} {period} {count_off} {count_on} {ratio}");
} else {
println!("{wrapx} {wrapy} {prob} Inf NaN NaN NaN NaN");
};
}
}
}
_ => todo!(),
}
}
}
@ -348,7 +367,7 @@ fn find_first_oscillation(g: &mut Grid, on: &[bool; 9], off: &[bool; 9], max_ste
}
let mut leading = g.clone();
for i in 0..period {
for _ in 0..period {
leading.step(on, off, true);
}

Loading…
Cancel
Save