diff --git a/ylong_runtime/src/iter/parallel/mod.rs b/ylong_runtime/src/iter/parallel/mod.rs index dda4e85036e557980a57c29d74b982f7eb845438..c78fbabdf0af503dbf8b91060d434792b09c505b 100644 --- a/ylong_runtime/src/iter/parallel/mod.rs +++ b/ylong_runtime/src/iter/parallel/mod.rs @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::pariter::ParallelIterator; +use super::pariter::{ParallelIterator, ZipParallelIterator}; /// Parallel iterator implementation for array pub mod array; @@ -127,3 +127,5 @@ impl ParallelIterator for ParIter { (left, right) } } + +impl ZipParallelIterator for ParIter {} diff --git a/ylong_runtime/src/iter/pariter/map.rs b/ylong_runtime/src/iter/pariter/map.rs index e0e2ff5e790ace61e29323e647b0342e5ef0c864..94898b93ccb2765748ef6bc72ccd168b231574d6 100644 --- a/ylong_runtime/src/iter/pariter/map.rs +++ b/ylong_runtime/src/iter/pariter/map.rs @@ -13,7 +13,7 @@ use std::iter; -use super::ParallelIterator; +use super::{ParallelIterator, ZipParallelIterator}; pub fn map(par_iter: P, map_op: F) -> Map { Map { @@ -63,3 +63,10 @@ where self.base.iter().map(self.map_op) } } + +impl ZipParallelIterator for Map +where + P: ZipParallelIterator, + F: Fn(P::Item) -> B + Copy + Send, +{ +} diff --git a/ylong_runtime/src/iter/pariter/mod.rs b/ylong_runtime/src/iter/pariter/mod.rs index a15087533ef1a248927f8c3ea4dc9f268939c4a1..4d13d7e5183901100b1666bf7d33968a20958db1 100644 --- a/ylong_runtime/src/iter/pariter/mod.rs +++ b/ylong_runtime/src/iter/pariter/mod.rs @@ -71,14 +71,6 @@ pub trait ParallelIterator: Sized + Send { filter::filter(self, predicate) } - /// Parallel version of the std iterator zip - fn zip(self, another: B) -> Zip - where - B: ParallelIterator, - { - zip::zip(self, another) - } - /// Execute the OP in parallel on each element produced by the parallel /// iterator. fn for_each<'a, F>( @@ -119,6 +111,17 @@ pub trait ParallelIterator: Sized + Send { } } +/// A subTrait of ParallelIterator for zip. +pub trait ZipParallelIterator: ParallelIterator { + /// Parallel version of the std iterator zip + fn zip(self, another: B) -> Zip + where + B: ZipParallelIterator, + { + zip::zip(self, another) + } +} + /// Consumer that comsume a parallel iterator and returns the result. pub trait Consumer { /// Type that the consumer return diff --git a/ylong_runtime/src/iter/pariter/zip.rs b/ylong_runtime/src/iter/pariter/zip.rs index d5d4ce395f1ade2ef9b26100de89dfe3cc6d101f..deb84e95c32ebd80c4c1eb796bd8310dbce9b90f 100644 --- a/ylong_runtime/src/iter/pariter/zip.rs +++ b/ylong_runtime/src/iter/pariter/zip.rs @@ -13,7 +13,7 @@ use std::iter; -use super::ParallelIterator; +use super::{ParallelIterator, ZipParallelIterator}; pub fn zip(mut a: A, mut b: B) -> Zip where @@ -72,3 +72,10 @@ where self.a.iter().zip(self.b.iter()) } } + +impl ZipParallelIterator for Zip +where + A: ZipParallelIterator, + B: ZipParallelIterator, +{ +} diff --git a/ylong_runtime/src/iter/prelude.rs b/ylong_runtime/src/iter/prelude.rs index 48a3180f279fc479fefb4bb644a6fb6a14e08824..d3fe1e8264ae267e863cc050b9d537629791381a 100644 --- a/ylong_runtime/src/iter/prelude.rs +++ b/ylong_runtime/src/iter/prelude.rs @@ -12,4 +12,4 @@ // limitations under the License. pub use crate::iter::parallel::{AsParIter, AsParIterMut, IntoParIter}; -pub use crate::iter::pariter::ParallelIterator; +pub use crate::iter::pariter::{ParallelIterator, ZipParallelIterator}; diff --git a/ylong_runtime/tests/par_iter.rs b/ylong_runtime/tests/par_iter.rs index 322a38463b76432023802d646ecfb570dcd1dc93..f5ae3724bbe13359339d79a6f1873615e49326a0 100644 --- a/ylong_runtime/tests/par_iter.rs +++ b/ylong_runtime/tests/par_iter.rs @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; /// SDV test cases for par_iter /// @@ -19,45 +19,288 @@ use std::collections::{HashMap, HashSet}; /// 1. Creates a parallel iterator and adds elements together. /// 2. Checks the correctness of the answer. use ylong_runtime::iter::prelude::*; + +macro_rules! test { + ($a:ident, $b:ident) => { + let fut = async { + let sum = $a + .clone() + .into_par_iter() + .map(|x| x + 1) + .sum() + .await + .unwrap(); + assert_eq!(sum, 65); + + let sum = $a + .clone() + .into_par_iter() + .map(|x| x + 1) + .filter(|x| x <= &5) + .sum() + .await + .unwrap(); + assert_eq!(sum, 14); + + let sum = $a + .clone() + .into_par_iter() + .zip($b.clone().into_par_iter()) + .map(|x| x.0 + x.1) + .sum() + .await + .unwrap(); + assert_eq!(sum, 24); + + let sum = $a + .into_par_iter() + .zip($b.into_par_iter()) + .map(|x| x.0 + x.1) + .filter(|x| x < &8) + .sum() + .await + .unwrap(); + assert_eq!(sum, 15); + }; + ylong_runtime::block_on(fut); + }; +} + +macro_rules! test2 { + ($a:ident, $b:ident) => { + let fut = async { + let sum = $a + .clone() + .into_par_iter() + .map(|x| x.1 + 1) + .sum() + .await + .unwrap(); + assert_eq!(sum, 65); + + let sum = $a + .clone() + .into_par_iter() + .map(|x| x.1 + 1) + .filter(|x| x <= &5) + .sum() + .await + .unwrap(); + assert_eq!(sum, 14); + + let sum = $a + .clone() + .into_par_iter() + .zip($b.clone().into_par_iter()) + .map(|x| x.0 .1 + x.1 .1) + .sum() + .await + .unwrap(); + assert_eq!(sum, 24); + + let sum = $a + .into_par_iter() + .zip($b.into_par_iter()) + .map(|x| x.0 .1 + x.1 .1) + .filter(|x| x < &8) + .sum() + .await + .unwrap(); + assert_eq!(sum, 15); + }; + ylong_runtime::block_on(fut); + }; +} + +#[test] +fn sdv_par_iter_vec_test() { + let a = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let b = vec![2, 3, 4, 5]; + test!(a, b); +} + +#[test] +fn sdv_par_iter_array_test() { + let a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let b = [2, 3, 4, 5]; + test!(a, b); +} + +#[test] +fn sdv_par_iter_slice_test() { + let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let a = &data[0..]; + let b = &data[1..5]; + test!(a, b); +} + #[test] -fn sdv_par_iter_test() { +fn sdv_par_iter_binary_heap_test() { + let mut a = BinaryHeap::new(); + let mut b = BinaryHeap::new(); + for i in 1..11 { + a.push(i); + } + for i in 2..6 { + b.push(i); + } let fut = async { - let a = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let b = vec![2, 3, 4, 5]; + let sum = a + .clone() + .into_par_iter() + .map(|x| x + 1) + .sum() + .await + .unwrap(); + assert_eq!(sum, 65); let sum = a - .par_iter() - .map(|x| *x + 1) - .filter(|x| *x < 5) - .zip(b.par_iter()) - .map(|x| x.0 * (*x.1)) + .clone() + .into_par_iter() + .map(|x| x + 1) + .filter(|x| x <= &5) .sum() .await .unwrap(); - assert_eq!(sum, 29); + assert_eq!(sum, 14); - let s = a.iter().copied().collect::>(); - let sum = s.into_par_iter().sum().await.unwrap(); - assert_eq!(sum, 55); + let sum = a + .clone() + .into_par_iter() + .zip(b.clone().into_par_iter()) + .map(|x| x.0 + x.1) + .sum() + .await + .unwrap(); + assert_eq!(sum, 46); - let m = a - .iter() - .zip(b.iter()) - .map(|x| (*x.0, *x.1)) - .collect::>(); - let sum = m.into_par_iter().map(|x| x.0 * x.1).sum().await.unwrap(); - assert_eq!(sum, 40); + let sum = a + .into_par_iter() + .zip(b.into_par_iter()) + .map(|x| x.0 + x.1) + .filter(|x| x < &8) + .sum() + .await + .unwrap(); + assert_eq!(sum, 0); + }; + ylong_runtime::block_on(fut); +} + +#[test] +fn sdv_par_iter_btree_map_test() { + let mut a = BTreeMap::new(); + for i in 1..11 { + a.insert(i, i); + } + let mut b = BTreeMap::new(); + for i in 2..6 { + b.insert(i, i); + } + test2!(a, b); +} + +#[test] +fn sdv_par_iter_btree_set_test() { + let mut a = BTreeSet::new(); + for i in 1..11 { + a.insert(i); + } + let mut b = BTreeSet::new(); + for i in 2..6 { + b.insert(i); + } + test!(a, b); +} + +#[test] +fn sdv_par_iter_link_list_test() { + let mut a = LinkedList::new(); + for i in 1..11 { + a.push_back(i); + } + let mut b = LinkedList::new(); + for i in 2..6 { + b.push_back(i); + } + test!(a, b); +} +#[test] +fn sdv_par_iter_vec_deque_test() { + let mut a = VecDeque::new(); + for i in 1..11 { + a.push_back(i); + } + let mut b = VecDeque::new(); + for i in 2..6 { + b.push_back(i); + } + test!(a, b); +} + +#[test] +fn sdv_par_iter_hash_map_test() { + let mut a = HashMap::new(); + for i in 1..11 { + a.insert(i, i); + } + let mut b = HashMap::new(); + for i in 2..6 { + b.insert(i, i); + } + let fut = async { let sum = a + .clone() + .into_par_iter() + .map(|x| x.1 + 1) + .sum() + .await + .unwrap(); + assert_eq!(sum, 65); + + let sum = a + .clone() + .into_par_iter() + .map(|x| x.1 + 1) + .filter(|x| x <= &5) + .sum() + .await + .unwrap(); + assert_eq!(sum, 14); + }; + ylong_runtime::block_on(fut); +} + +#[test] +fn sdv_par_iter_hash_set_test() { + let mut a = HashSet::new(); + for i in 1..11 { + a.insert(i); + } + let mut b = HashSet::new(); + for i in 2..6 { + b.insert(i); + } + let fut = async { + let sum = a + .clone() .into_par_iter() .map(|x| x + 1) - .filter(|x| *x < 5) - .zip(b.into_par_iter()) - .map(|x| x.0 * x.1) .sum() .await .unwrap(); - assert_eq!(sum, 29); + assert_eq!(sum, 65); + + let sum = a + .clone() + .into_par_iter() + .map(|x| x + 1) + .filter(|x| x <= &5) + .sum() + .await + .unwrap(); + assert_eq!(sum, 14); }; ylong_runtime::block_on(fut); }