Skip to content

Commit 054d670

Browse files
committed
Update scan PR with changes from rayon-scan
- Refactor tests/bench - Add new tests - Minor fix to splitting in scan algorithm Thanks to François Garillot for some of the changes.
1 parent d0b83c0 commit 054d670

File tree

5 files changed

+148
-117
lines changed

5 files changed

+148
-117
lines changed

rayon-demo/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ mod map_collect;
2828
#[cfg(test)]
2929
mod pythagoras;
3030
#[cfg(test)]
31+
mod scan;
32+
#[cfg(test)]
3133
mod sort;
3234
#[cfg(test)]
3335
mod str_split;
3436
#[cfg(test)]
3537
mod tree;
3638
#[cfg(test)]
3739
mod vec_collect;
38-
#[cfg(test)]
39-
mod scan;
4040

4141
#[cfg(test)]
4242
extern crate test;

rayon-demo/src/scan/bench.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use std::time::{Duration, Instant};
2+
3+
use super::scan::{scan_matmul, scan_parallel, scan_sequential, Procs};
4+
5+
/******* Addition with artificial delay *******/
6+
7+
const DELAY: Duration = Duration::from_nanos(10);
8+
fn wait() -> i32 {
9+
let time = Instant::now();
10+
11+
let mut sum = 0;
12+
while time.elapsed() < DELAY {
13+
sum += 1;
14+
}
15+
sum
16+
}
17+
18+
fn scan_add(procs: Procs) -> Vec<i32> {
19+
let init = || 2;
20+
let id = 0;
21+
22+
match procs {
23+
Procs::Sequential => {
24+
let f = |state: &mut i32, x: &i32| {
25+
test::black_box(wait());
26+
*state += x;
27+
Some(*state)
28+
};
29+
scan_sequential(init, id, f)
30+
}
31+
Procs::Parallel => {
32+
let f = |x: &i32, y: &i32| {
33+
test::black_box(wait());
34+
*x + *y
35+
};
36+
scan_parallel(init, id, f)
37+
}
38+
}
39+
}
40+
41+
#[test]
42+
fn test_scan_add() {
43+
assert_eq!(scan_add(Procs::Sequential), scan_add(Procs::Parallel));
44+
}
45+
46+
#[bench]
47+
fn scan_add_sequential(b: &mut test::Bencher) {
48+
b.iter(|| scan_add(Procs::Sequential));
49+
}
50+
51+
#[bench]
52+
fn scan_add_parallel(b: &mut test::Bencher) {
53+
b.iter(|| scan_add(Procs::Parallel));
54+
}
55+
56+
#[bench]
57+
fn scan_matmul_sequential(b: &mut test::Bencher) {
58+
b.iter(|| scan_matmul(Procs::Sequential, 50));
59+
}
60+
61+
#[bench]
62+
fn scan_matmul_parallel(b: &mut test::Bencher) {
63+
b.iter(|| scan_matmul(Procs::Parallel, 50));
64+
}

rayon-demo/src/scan/mod.rs

Lines changed: 21 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,124 +1,32 @@
1-
use ndarray::{Array, Dim};
21
use rayon::iter::*;
3-
use std::time::{Duration, Instant};
4-
use std::num::Wrapping;
52

6-
const SIZE: usize = 10000;
7-
8-
enum Procs {
9-
Sequential,
10-
Parallel,
11-
}
12-
13-
fn scan_sequential<T, P, I>(init: I, id: T, scan_op: P) -> Vec<T>
14-
where
15-
T: Clone,
16-
I: Fn() -> T,
17-
P: FnMut(&mut T, &T) -> Option<T>,
18-
{
19-
let v = vec![init(); SIZE];
20-
let scan = v.iter().scan(id, scan_op);
21-
scan.collect()
22-
}
23-
24-
fn scan_parallel<T, P, I>(init: I, id: T, scan_op: P) -> Vec<T>
25-
where
26-
T: Clone + Send + Sync,
27-
I: Fn() -> T,
28-
P: Fn(&T, &T) -> T + Sync,
29-
{
30-
let v = vec![init(); SIZE];
31-
let scan = v.into_par_iter().with_min_len(SIZE / 100).scan(&scan_op, id);
32-
scan.collect()
33-
}
34-
35-
/******* Addition with artificial delay *******/
36-
37-
const DELAY: Duration = Duration::from_nanos(10);
38-
fn wait() -> i32 {
39-
let time = Instant::now();
40-
41-
let mut sum = 0;
42-
while time.elapsed() < DELAY {
43-
sum += 1;
44-
}
45-
sum
46-
}
47-
48-
fn scan_add(procs: Procs) -> Vec<i32> {
49-
let init = || 2;
50-
let id = 0;
51-
52-
match procs {
53-
Procs::Sequential => {
54-
let f = |state: &mut i32, x: &i32| {
55-
test::black_box(wait());
56-
*state += x;
57-
Some(*state)
58-
};
59-
scan_sequential(init, id, f)
60-
}
61-
Procs::Parallel => {
62-
let f = |x: &i32, y: &i32| {
63-
test::black_box(wait());
64-
*x + *y
65-
};
66-
scan_parallel(init, id, f)
67-
}
68-
}
69-
}
70-
71-
#[bench]
72-
fn scan_add_sequential(b: &mut test::Bencher) {
73-
b.iter(|| scan_add(Procs::Sequential));
74-
}
75-
76-
#[bench]
77-
fn scan_add_parallel(b: &mut test::Bencher) {
78-
b.iter(|| scan_add(Procs::Parallel));
79-
}
3+
mod scan;
4+
use self::scan::{scan_matmul, Procs};
805

816
#[test]
82-
fn test_scan_add() {
83-
assert_eq!(scan_add(Procs::Sequential), scan_add(Procs::Parallel));
7+
fn test_scan_matmul() {
8+
assert_eq!(
9+
scan_matmul(Procs::Sequential, 10),
10+
scan_matmul(Procs::Parallel, 10)
11+
);
8412
}
8513

86-
/******** Matrix multiplication with wrapping arithmetic *******/
87-
88-
type Matrix = Array<Wrapping<i32>, Dim<[usize; 2]>>;
89-
fn scan_matmul(procs: Procs) -> Vec<Matrix> {
90-
const MAT_SIZE: usize = 50;
91-
let init = || {
92-
Array::from_iter((0..((MAT_SIZE * MAT_SIZE) as i32)).map(|x| Wrapping(x)))
93-
.into_shape((MAT_SIZE, MAT_SIZE))
94-
.unwrap()
14+
#[test]
15+
fn test_scan_addition() {
16+
let init = 0u64;
17+
let op = |state: &mut u64, x: &u64| {
18+
*state += x;
19+
Some(*state)
9520
};
96-
let id = Array::eye(MAT_SIZE);
97-
98-
match procs {
99-
Procs::Sequential => {
100-
let f = |state: &mut Matrix, x: &Matrix| {
101-
*state = state.dot(x);
102-
Some(state.clone())
103-
};
21+
let op_par = |state: &u64, x: &u64| *state + x;
10422

105-
scan_sequential(init, id, f)
106-
}
107-
Procs::Parallel => scan_parallel(init, id, |x, y| x.dot(y)),
23+
for len in 0..100 {
24+
let v = vec![1u64; len];
25+
let scan_seq = v.iter().scan(init, op).collect::<Vec<u64>>();
26+
let scan_par = v.into_par_iter().scan(op_par, init).collect::<Vec<u64>>();
27+
assert_eq!(scan_seq, scan_par);
10828
}
10929
}
11030

111-
#[bench]
112-
fn scan_matmul_sequential(b: &mut test::Bencher) {
113-
b.iter(|| scan_matmul(Procs::Sequential));
114-
}
115-
116-
#[bench]
117-
fn scan_matmul_parallel(b: &mut test::Bencher) {
118-
b.iter(|| scan_matmul(Procs::Parallel));
119-
}
120-
121-
#[test]
122-
fn test_scan_matmul() {
123-
assert_eq!(scan_matmul(Procs::Sequential), scan_matmul(Procs::Parallel));
124-
}
31+
#[cfg(test)]
32+
mod bench;

rayon-demo/src/scan/scan.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use ndarray::{Array, Dim};
2+
use rayon::iter::*;
3+
use std::num::Wrapping;
4+
5+
const SIZE: usize = 10000;
6+
7+
pub enum Procs {
8+
Sequential,
9+
Parallel,
10+
}
11+
12+
pub fn scan_sequential<T, P, I>(init: I, id: T, scan_op: P) -> Vec<T>
13+
where
14+
T: Clone,
15+
I: Fn() -> T,
16+
P: FnMut(&mut T, &T) -> Option<T>,
17+
{
18+
let v = vec![init(); SIZE];
19+
let scan = v.iter().scan(id, scan_op);
20+
scan.collect()
21+
}
22+
23+
pub fn scan_parallel<T, P, I>(init: I, id: T, scan_op: P) -> Vec<T>
24+
where
25+
T: Clone + Send + Sync,
26+
I: Fn() -> T,
27+
P: Fn(&T, &T) -> T + Sync,
28+
{
29+
let v = vec![init(); SIZE];
30+
let scan = v
31+
.into_par_iter()
32+
.with_min_len(SIZE / 100)
33+
.scan(&scan_op, id);
34+
scan.collect()
35+
}
36+
37+
/******** Matrix multiplication with wrapping arithmetic *******/
38+
39+
type Matrix = Array<Wrapping<i32>, Dim<[usize; 2]>>;
40+
pub fn scan_matmul(procs: Procs, mat_size: usize) -> Vec<Matrix> {
41+
let init = || {
42+
Array::from_iter((0..((mat_size * mat_size) as i32)).map(|x| Wrapping(x)))
43+
.into_shape((mat_size, mat_size))
44+
.unwrap()
45+
};
46+
let id = Array::eye(mat_size);
47+
48+
match procs {
49+
Procs::Sequential => {
50+
let f = |state: &mut Matrix, x: &Matrix| {
51+
*state = state.dot(x);
52+
Some(state.clone())
53+
};
54+
55+
scan_sequential(init, id, f)
56+
}
57+
Procs::Parallel => scan_parallel(init, id, |x, y| x.dot(y)),
58+
}
59+
}

src/iter/scan.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::plumbing::*;
22
use super::*;
3-
use std::usize;
43
use std::collections::LinkedList;
4+
use std::usize;
55

66
pub(super) fn scan<PI, P, T>(pi: PI, scan_op: P, id: T) -> Scan<T, P>
77
where
@@ -218,7 +218,7 @@ where
218218
type Item = T;
219219

220220
fn split(self) -> (Self, Option<Self>) {
221-
let mid = self.offsets.len() / 2;
221+
let mid = self.data.len() / 2;
222222
if mid == 0 {
223223
return (self, None);
224224
}

0 commit comments

Comments
 (0)