Estimated time: 1 day
One of main Rust's design goals is a concurrency. Rust has a strong opinion about that, while allows different concurrent models to coexist.
Rust has built-in support for native threads in a form of std::thread
module of standard library.
Traditionally, threads are used for solving CPU-bound problems, as they allow to execute tasks in parallel. However, in practice, threads are often used to solve I/O-bound problems too, especially when asynchronous I/O is not supported well (which is true for Rust std
library at the moment).
crossbeam crate also provides implementation of scoped threads, which allow to borrow values from a stack.
For better understanding Rust threads design, concepts, usage, and features (especially TLS is important and widely used one), read through the following articles:
- Rust Book: 16.1. Using Threads to Run Code Simultaneously
- Rust By Example: 20.1. Threads
- Official
std::thread
docs
The threads synchronization is a wide topic, but generally it's done via atomic operations, shared state with an exclusive access, or by threads communication. Rust has built-in support for all of them.
Atomic operations are represented by std::sync::atomic
module of standard library.
Exclusive access may be controlled via primitives of std::sync
module of standard library.
Threads communication is commonly represented via channels and is implemented in std::sync::mpsc
module of standard library.
Despite that, there is also crossbeam crate, which provides more feature-rich and optimized concurrency and synchronization primitives. The most notable is crossbeam-channel as an enhancement of std
channel implementations.
For better understanding and familiarity with Rust synchronization primitives design, concepts, usage, and features, read through the following articles:
- Rust Book: 16.2. Using Message Passing to Transfer Data Between Threads
- Rust Book: 16.3. Shared-State Concurrency
- Rust Blog: Fearless Concurrency with Rust
- Official
std::sync
docs - Official
std::sync::atomic
docs - Official
std::sync::mpsc
docs - Official
crossbeam-channel
crate docs - Carl Fredrik Samson: Explaining Atomics in Rust
- Aleksey Kladov: Mutexes Are Faster Than Spinlocks
The important concept to understand is how concurrency and parallelism differ.
Rust ecosystem has support for parallelism in form of rayon crate, which makes it easy to convert a sequential iterator to execute in parallel threads.
Another way to perform parallel data processing without using threads is SIMD instructions usage. If an algorithm is parallelizable enough, applying SIMD instructions may increase performance drastically. Rust ecosystem provides basic support for SIMD instructions in a form of packed_simd crate.
For better understanding and familiarity with parallelism in Rust, read through the following articles:
- Official
rayon
crate docs rayon
crate FAQrayon
crate demos- Rust Edition Guide: 3.9. SIMD for faster computing
- Official
packed_simd
crate docs
Write a program with the following workflow:
Producer
is a separate thread, which continuously generates square matrixes of randomu8
elements and size4096
.Consumer
is a separate thread, which takes a generated matrix, counts sum of all its elements and prints the sum to STDOUT.- There are only 1
Producer
and 2Consumer
s. - Counting sum of matrix elements should be parallelized.