rayon
rayon turns sequential iterators into parallel ones with a work-stealing thread pool. It shines on CPU-bound data processing without manual thread management.
Search across all documentation pages
rayon turns sequential iterators into parallel ones with a work-stealing thread pool. It shines on CPU-bound data processing without manual thread management.
[dependencies]
rayon = "1.10"use rayon::prelude::*;
fn main() {
let sum: u64 = (0..1_000_000u64).into_par_iter().sum();
assert_eq!(sum, 499_999_500_000);
}When to reach for this:
Vecsuse rayon::prelude::*;
#[derive(Debug)]
struct Row { value: i32 }
fn normalize(rows: &mut [Row]) {
rows.par_iter_mut().for_each(|r| {
r.value = r.value.saturating_mul(2);
});
}
fn main() {
let mut data: Vec<Row> = (0..10_000).map(|i| Row { value: i }).collect();
normalize(&mut data);
assert_eq!(data[100].value, 200);
}What this demonstrates:
par_iter / par_iter_mut mirror std iteratorsMutex for independent elements| Method | Use |
|---|---|
par_iter().map() | Transform collections |
par_chunks() | Slice-based parallelism |
join | Recursive divide-and-conquer |
ThreadPoolBuilder | Custom thread count |
Do not run rayon inside async tasks without spawn_blocking. Pattern:
let out = tokio::task::spawn_blocking(move || {
data.par_iter().map(|x| x * 2).collect::<Vec<_>>()
}).await?;par_iter_mut needs disjoint access. Fix: use channels or map-reduce.Rc across threads fails. Fix: Arc or owned data per task.for_each is unordered. Fix: map then collect if order matters.| Alternative | Use When | Don't Use When |
|---|---|---|
std::thread::scope | Few explicit threads | Large data parallelism |
Tokio spawn_blocking | Occasional CPU in server | Heavy parallel maps |
ndarray + BLAS | Numeric linear algebra | Generic collections |
Default pool size matches logical cores. Configure with ThreadPoolBuilder.
Yes. Rayon APIs enforce Send and borrow rules at compile time.
Possible but often oversubscribes CPUs. Prefer flat parallel pipeline.
Polars has internal parallelism. Use rayon for custom Rust logic outside DataFrames.
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.
Reviewed by Chris St. John·Last updated Jul 16, 2026