rust-rayon
Skill0 starsChanged 35 days agoMITView on GitHub
Use when adding data parallelism to Rust with rayon.
In this repository15 other files it gives its agents.
- AGENTS.mdAGENTS.md
- rustoriaSkill
- rust-debuggingSkill
- rust-dependenciesSkill
- rust-fundamentalsSkill
- rust-axumSkill
- rust-clapSkill
- rust-dieselSkill
- rust-ratatuiSkill
- rust-serdeSkill
- rust-tokioSkill
- rust-productionSkill
- rust-code-auditSkill
- rust-stdSkill
- rust-unsafe-checkerSkill
The file
Files
Rayon — Data Parallelism for Rust
Overview
Rayon is a data-parallelism library that makes it easy to convert sequential computations into parallel ones. It guarantees data-race freedom and dynamically adapts for maximum performance.
Installation
[dependencies]
rayon = "1.12"Core Concepts
1. Parallel Iterators
The simplest way to use Rayon — just change .iter() to .par_iter():
use rayon::prelude::*;
fn sum_of_squares(input: &[i32]) -> i32 {
input.par_iter()
.map(|&i| i * i)
.sum()
}
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
let sum = sum_of_squares(&numbers);
println!("Sum of squares: {}", sum);
}2. Parallel Operations
// Fragment — statements assume a surrounding `fn main()`.
use rayon::prelude::*;
let numbers = vec![1, 2, 3, 4, 5];
// Parallel map
let squares: Vec<i32> = numbers.par_iter()
.map(|&x| x * x)
.collect();
// Parallel filter
let evens: Vec<&i32> = numbers.par_iter()
.filter(|&&x| x % 2 == 0)
.collect();
// Parallel for_each
numbers.par_iter()
.for_each(|x| println!("{}", x));
// Parallel reduce - needs an identity element plus an associative op; items are
// &i32, so copy them out first (identity and op must yield the item type)
let sum = numbers.par_iter()
.copied()
.reduce(|| 0, |a, b| a + b);
// Parallel fold + reduce — same identity requirement on reduce
let sum = numbers.par_iter()
.fold(|| 0, |a, &b| a + b)
.reduce(|| 0, |a, b| a + b);
// No identity element? Use reduce_with — returns Option (None on empty input)
let max: Option<i32> = numbers.par_iter()
.copied()
.reduce_with(|a, b| a.max(b));3. Parallel Sort
// Fragment — statements assume a surrounding `fn main()`.
use rayon::prelude::*;
let mut numbers = vec![5, 2, 8, 1, 9, 3];
numbers.par_sort();
// or
numbers.par_sort_by(|a, b| b.cmp(a)); // descending4. Custom Tasks with Join
A teaching example of divide-and-conquer with join — for real sorting use par_sort (§3):
use rayon::join;
fn partition<T: Ord>(slice: &mut [T]) -> usize {
let pivot = slice.len() - 1;
let mut i = 0;
for j in 0..pivot {
if slice[j] <= slice[pivot] {
slice.swap(i, j);
i += 1;
}
}
slice.swap(i, pivot);
i
}
fn quicksort<T: Ord + Send>(slice: &mut [T]) {
if slice.len() <= 1 {
return;
}
let pivot = partition(slice);
let (left, right) = slice.split_at_mut(pivot);
join(
|| quicksort(left),
|| quicksort(&mut right[1..]), // right[0] is the pivot, already placed
);
}
fn main() {
let mut data = vec![5, 2, 8, 1, 9, 3];
quicksort(&mut data);
assert_eq!(data, [1, 2, 3, 5, 8, 9]);
}5. Scopes
// Fragment — statements assume a surrounding `fn main()`.
use rayon::scope;
scope(|s| {
s.spawn(|_| {
println!("Running in parallel");
});
s.spawn(|_| {
println!("Also running in parallel");
});
});
// Blocks until all spawned tasks complete6. Custom Thread Pools
// Fragment — statements assume a surrounding `fn main()`.
use rayon::prelude::*;
use rayon::ThreadPoolBuilder;
let pool = ThreadPoolBuilder::new()
.num_threads(4)
.build()
.unwrap();
pool.install(|| {
// This closure runs on the custom pool
let sum = (0..1000).into_par_iter().sum::<i32>();
println!("Sum: {}", sum);
});7. Parallel Collections
// Fragment — statements assume a surrounding `fn main()`.
use rayon::prelude::*;
// Parallel extend
let mut vec = Vec::new();
vec.par_extend((0..1000).into_par_iter());
// Parallel slice operations
let slice: &[i32] = &[1, 2, 3, 4, 5];
let sum = slice.par_iter().sum::<i32>();
// Parallel string search — &str has no par_iter; use the ParallelString methods
let text = "hello world";
let found = text.par_chars().any(|c| c == 'w');
let has_long_word = text.par_split(' ').any(|w| w.len() > 4);8. Performance Considerations
Parallelism has per-task overhead (work stealing, synchronization, allocations in collect). For tiny inputs or trivial
per-element work, the sequential version is faster:
// Fragment — the loose statements assume a surrounding `fn main()`.
use rayon::prelude::*;
let small = vec![1, 2, 3];
let sum: i32 = small.iter().sum(); // sequential: cheaper here
// There is no universal size threshold. Break-even depends on per-element
// cost, cache behavior, and core count — the 10_000 below is a starting
// guess, not a rule. MEASURE your real workload (benchmark with criterion;
// see the testing skill) and pick the crossover from data.
fn total(numbers: &[i32]) -> i32 {
if numbers.len() < 10_000 {
numbers.iter().sum()
} else {
numbers.par_iter().sum()
}
}Also: use par_iter() for CPU-bound work only. For I/O-bound concurrency, use an async runtime (tokio) instead —
rayon threads block on I/O just like any other thread.
9. Best Practices
- Use
par_iter()for CPU-bound work — not I/O - Avoid side effects in parallel closures (order is non-deterministic)
reduceneeds an identity element — usereduce_with(returnsOption) when no identity exists- Use
par_sortfor large datasets - Use
scopefor tasks that need to borrow stack data - Use
ThreadPoolBuilderfor custom thread pools - Measure before parallelizing — overhead dominates on small/cheap workloads; benchmark to find your break-even point
- Combine with
Arcfor shared read-only data
When to Use Rayon
- CPU-bound parallel computation
- Data processing pipelines
- Parallel sorting
- Image processing
- Scientific computing
- Any workload that can be expressed as parallel iterators
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

