jeudi 8 novembre 2018

Rust - Threads deadlocking when generating random numbers

I'm writing a simple program that reads lines from a file and generates random numbers based on each line, for example, "20d40" will generate 20 random numbers from 1 to 40 and print their sum.

I was trying to optimize by using the rayon package to parallelize, after the sequential version was working.

fn do_it(line :&[u8]) {
    if line.len() < 1 { return; }
    let mut rolls :u64 = 0;
    let mut faces :u64 = 0;
    let mut pre_d = true;
    for c in line {
        if *c == 100 { // *c == 'd'
            pre_d = !pre_d;
            continue;
        }
        if pre_d {
            rolls = (rolls * 10) + ((*c as u64) - 48);
        }else{
            faces = (faces * 10) + ((*c as u64) - 48);
        }
    }
    let mut sum :u64 = 0;
    let mut rng = SmallRng::from_entropy();
    println!("{:?} I", thread::current().id());
    for _i in 0..rolls { // Deadlock in this for loop
        sum += 1 + rng.gen::<u64>() % faces;
    }
    println!("{:?} F", thread::current().id());
    println!("{}", sum);
}

fn main() -> std::io::Result<()> {
    let file = File::open("input.txt")?;
    let mut buf_reader = BufReader::new(file);
    let mut contents = String::new();
    buf_reader.read_to_string(&mut contents)?;
   iter::split(contents.as_bytes(), |c| {
        match Memchr::new(10, &c).next() {
            Some(new_line) => {
                let (a, b) = c.split_at(new_line);
                if b.len() < 1 {
                    (a, None)
                }else{
                    (a, Some(&b[1..]))
                }
            },
            None => (c,  None),
        }
      }).for_each(|line| do_it(line));
    Ok(())
}

This code produces an output like this:

ThreadId(1) I
ThreadId(1) F
1937
ThreadId(1) I
ThreadId(1) F
3908
ThreadId(1) I
ThreadId(1) F
3575
ThreadId(1) I
ThreadId(1) F
3906
ThreadId(1) I
ThreadId(1) F
238
ThreadId(3) I
ThreadId(3) F
2793
ThreadId(2) I
ThreadId(2) F
4962
ThreadId(4) I
ThreadId(4) F
1690
ThreadId(1) I
^C

I had to ^C at the end because it just hangs there. The number threads that run before it hangs is random




Aucun commentaire:

Enregistrer un commentaire