ndarray/parallel/mod.rs
1//! Parallelization features for ndarray.
2//!
3//! Parallelization features are based on the crate [rayon] and its parallel
4//! iterators. Ndarray implements the parallel iterable traits for arrays
5//! and array views, for some of its iterators and for [Zip].
6//! There are also directly parallelized methods on arrays and on [Zip].
7//!
8//! This requires the crate feature `rayon` to be enabled.
9//!
10//! The following types implement parallel iterators, accessed using these
11//! methods:
12//!
13//! - [`Array`], [`ArcArray`] `.par_iter()` and `.par_iter_mut()`
14//! - [`ArrayView`] `.into_par_iter()`
15//! - [`ArrayViewMut`] `.into_par_iter()`
16//! - [`AxisIter`], [`AxisIterMut`] `.into_par_iter()`
17//! - [`AxisChunksIter`], [`AxisChunksIterMut`] `.into_par_iter()`
18//! - [`Zip`] `.into_par_iter()`
19//!
20//! The following other parallelized methods exist:
21//!
22//! - [`ArrayBase::par_map_inplace()`]
23//! - [`ArrayBase::par_mapv_inplace()`]
24//! - [`Zip::par_for_each()`] (all arities)
25//! - [`Zip::par_map_collect()`] (all arities)
26//! - [`Zip::par_map_assign_into()`] (all arities)
27//!
28//! Note that you can use the parallel iterator for [Zip] to access all other
29//! rayon parallel iterator methods.
30//!
31//! Only the axis iterators are indexed parallel iterators, the rest are all
32//! “unindexed”. Use ndarray’s [Zip] for lock step parallel iteration of
33//! multiple arrays or producers at a time.
34//!
35//! For the unindexed parallel iterators, an inherent method [`with_min_len`](Parallel::with_min_len)
36//! is provided to limit the number of elements each parallel task processes in way that is
37//! similar to Rayon's [`IndexedParallelIterator::with_min_len`](rayon::prelude::IndexedParallelIterator::with_min_len).
38//!
39//! # Examples
40//!
41//! ## Arrays and array views
42//!
43//! Compute the exponential of each element in an array, parallelized.
44//!
45//! ```
46//! use ndarray::Array2;
47//! use ndarray::parallel::prelude::*;
48//!
49//! let mut a = Array2::<f64>::zeros((128, 128));
50//!
51//! // Parallel versions of regular array methods
52//! a.par_map_inplace(|x| *x = x.exp());
53//! a.par_mapv_inplace(f64::exp);
54//!
55//! // You can also use the parallel iterator directly
56//! a.par_iter_mut().for_each(|x| *x = x.exp());
57//! ```
58//!
59//! ## Axis iterators
60//!
61//! Use the parallel `.axis_iter()` to compute the sum of each row.
62//!
63//! ```
64//! use ndarray::Array;
65//! use ndarray::Axis;
66//! use ndarray::parallel::prelude::*;
67//!
68//! let a = Array::linspace(0., 63., 64).into_shape_with_order((4, 16)).unwrap();
69//! let mut sums = Vec::new();
70//! a.axis_iter(Axis(0))
71//! .into_par_iter()
72//! .map(|row| row.sum())
73//! .collect_into_vec(&mut sums);
74//!
75//! assert_eq!(sums, [120., 376., 632., 888.]);
76//! ```
77//!
78//! ## Axis chunks iterators
79//!
80//! Use the parallel `.axis_chunks_iter()` to process your data in chunks.
81//!
82//! ```
83//! use ndarray::Array;
84//! use ndarray::Axis;
85//! use ndarray::parallel::prelude::*;
86//!
87//! let a = Array::linspace(0., 63., 64).into_shape_with_order((4, 16)).unwrap();
88//! let mut shapes = Vec::new();
89//! a.axis_chunks_iter(Axis(0), 3)
90//! .into_par_iter()
91//! .map(|chunk| chunk.shape().to_owned())
92//! .collect_into_vec(&mut shapes);
93//!
94//! assert_eq!(shapes, [vec![3, 16], vec![1, 16]]);
95//! ```
96//!
97//! ## Zip
98//!
99//! Use zip for lock step function application across several arrays
100//!
101//! ```
102//! use ndarray::Array3;
103//! use ndarray::Zip;
104//!
105//! type Array3f64 = Array3<f64>;
106//!
107//! const N: usize = 128;
108//! let a = Array3f64::from_elem((N, N, N), 1.);
109//! let b = Array3f64::from_elem(a.dim(), 2.);
110//! let mut c = Array3f64::zeros(a.dim());
111//!
112//! Zip::from(&mut c)
113//! .and(&a)
114//! .and(&b)
115//! .par_for_each(|c, &a, &b| {
116//! *c += a - b;
117//! });
118//! ```
119
120#[allow(unused_imports)] // used by rustdoc links
121use crate::iter::{AxisChunksIter, AxisChunksIterMut, AxisIter, AxisIterMut};
122#[allow(unused_imports)] // used by rustdoc links
123use crate::{ArcArray, Array, ArrayBase, ArrayView, ArrayViewMut, Zip};
124
125/// Into- traits for creating parallelized iterators and/or using [`par_azip!`]
126pub mod prelude
127{
128 #[doc(no_inline)]
129 pub use rayon::prelude::{
130 IndexedParallelIterator,
131 IntoParallelIterator,
132 IntoParallelRefIterator,
133 IntoParallelRefMutIterator,
134 ParallelIterator,
135 };
136
137 pub use super::par_azip;
138}
139
140pub use self::par::Parallel;
141pub use crate::par_azip;
142
143mod impl_par_methods;
144mod into_impls;
145mod par;
146mod send_producer;
147mod zipmacro;