rayon
rayon transforma iteradores sequenciais em paralelos com um pool de threads de roubo de trabalho (work-stealing). Ele se destaca em processamento de dados limitado pela CPU sem gerenciamento manual de threads.
Receita
[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);
}Quando usar isso:
- Transformações em lote em
Vecs grandes - Busca ou agregação paralela
- ETL offline, processamento de imagem, cargas de trabalho científicas
Exemplo de Trabalho
use 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);
}O que isso demonstra:
par_iter/par_iter_mutespelham os iteradoresstd- Rayon agenda o trabalho entre os threads
- Nenhum
Mutexmanual para elementos independentes
Mergulho Profundo
Padrões Paralelos
| Método | Uso |
|---|---|
par_iter().map() | Transformar coleções |
par_chunks() | Paralelismo baseado em fatias |
join | Dividir e conquistar recursivo |
ThreadPoolBuilder | Contagem de threads personalizada |
Com Tokio
Não execute rayon dentro de tarefas assíncronas sem spawn_blocking. Padrão:
let out = tokio::task::spawn_blocking(move || {
data.par_iter().map(|x| x * 2).collect::<Vec<_>>()
}).await?;Armadilhas
- Entradas pequenas - a sobrecarga de threads domina. Correção: paralelizar apenas acima de um limite (por exemplo, 10 mil itens).
- Mutação compartilhada -
par_iter_mutprecisa de acesso não sobreposto. Correção: usar canais ou map-reduce. - IO em rayon - bloqueia os threads do pool. Correção: manter IO no Tokio, CPU no rayon.
- Tipos não-Send -
Rcentre threads falha. Correção:Arcou dados de propriedade por tarefa. - Ordem não preservada -
for_eachnão é ordenado. Correção:mape depoiscollectse a ordem importar.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
std::thread::scope | Poucos threads explícitos | Paralelismo de dados em larga escala |
Tokio spawn_blocking | CPU ocasional em servidor | Mapeamentos paralelos intensos |
ndarray + BLAS | Álgebra linear numérica | Coleções genéricas |
FAQs
Rayon usa todas as CPUs?
O tamanho padrão do pool corresponde aos núcleos lógicos. Configure com ThreadPoolBuilder.
Seguro com a propriedade do Rust?
Sim. As APIs do Rayon impõem Send e regras de empréstimo em tempo de compilação.
Posso aninhar par_iter?
Possível, mas muitas vezes sobrecarrega as CPUs. Prefira pipeline paralelo plano.
Polars vs rayon?
Polars tem paralelismo interno. Use rayon para lógica Rust personalizada fora dos DataFrames.
Relacionado
- Paralelismo de dados com Rayon
- tokio - limite assíncrono
- Skill de Desempenho
- Polars - paralelismo de dataframe
Versões da Stack: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, e Polars 0.46+.