DEV Community 👩‍💻👨‍💻

Billy Chan
Billy Chan

Posted on

Multi-thread Processing in Rust

Most program we wrote is single threaded. Since most of the task is IO bound. It make sense to keep it simple by writing a single threaded program. But what if we have a CPU bound task? Let say, cracking a MD5 hash? Don't ask me why cracking MD5 hash, it's just one of CPU intensive task that I can think of, purely for demo purpose.

A naive hashing algorithm will be like this.

// Iterate from 0 util we found the target number
let mut i = 0_u32;
loop {
    // Hash our guessing number and compare with the target hash
    // Stop the loop if we found the target number
    if md5::compute(i.to_string()).eq(&TARGET_HASH) {
        break;
    }
    // What's our next guess?
    i += 1;
}
Enter fullscreen mode Exit fullscreen mode

For the hashing task we can distribute the work to N threads. With each thread start search the target number starting from N and continue the search by incrementing the number by N.

So, for example we've 3 threads. The search space for each thread would be:

Thread 1: 1, 4, 7, 10...
Thread 2: 2, 5, 8, 11...
Thread 3: 3, 6, 9, 12...
Enter fullscreen mode Exit fullscreen mode

That's how we divide the task to N threads with each thread work on a unique and non-overlapping search space.

// A MPSC channel to inform the main thread some worker found the solution
let (tx, rx) = mpsc::channel();
print!("Parallel hashing with {} threads: ", num_workers);

// Spawn workers
for worker in 0..num_workers {
    // Clone the transmission end and move it into the spawned worker
    let tx1 = tx.clone();
    thread::spawn(move || {
        // The guess number start from the worker number
        let mut i = worker;
        // Iterate from 0 util we found the target number
        loop {
            // Hash our guessing number and compare with the target hash
            let hash = md5::compute(i.to_string());
            // Stop the loop if we found the target number
            // And inform the main thread that we found the target number
            if hash.eq(&TARGET_HASH) {
                tx1.send("Found!").unwrap();
                break;
            }
            // What's our next guess?
            i += num_workers;
        }
    });
}

while let Ok(_) = rx.recv() {
    // Exit main thread, this will kill all spawn threads
    break;
}
Enter fullscreen mode Exit fullscreen mode

Source code available on GitHub.

Top comments (0)

DEV

Thank you.

 
Thanks for visiting DEV, we’ve worked really hard to cultivate this great community and would love to have you join us. If you’d like to create an account, you can sign up here.