1
1
//! Benchmarks for 0/1/2/3/N-dimensional linear interpolation
2
2
//! Run these with `cargo bench`
3
3
4
- use criterion:: { criterion_group, criterion_main, Criterion } ;
4
+ use criterion:: { black_box , criterion_group, criterion_main, Criterion } ;
5
5
6
6
use ndarray:: prelude:: * ;
7
7
use ninterp:: prelude:: * ;
8
- use rand:: { self , rngs:: StdRng , Rng , SeedableRng } ;
8
+
9
+ use ndarray_rand:: rand:: { prelude:: StdRng , Rng , SeedableRng } ;
10
+ use ndarray_rand:: rand_distr:: Uniform ;
11
+ use ndarray_rand:: RandomExt ;
12
+
13
+ const RANDOM_SEED : u64 = 1234567890 ;
9
14
10
15
#[ allow( non_snake_case) ]
11
16
/// 0-D interpolation (hardcoded)
@@ -18,130 +23,109 @@ fn benchmark_0D() {
18
23
/// 0-D interpolation (multilinear interpolator)
19
24
fn benchmark_0D_multi ( ) {
20
25
let interp_0d_multi = InterpND :: new (
21
- vec ! [ vec ![ ] ] ,
26
+ vec ! [ array ![ ] ] ,
22
27
array ! [ 0.5 ] . into_dyn ( ) ,
23
28
Linear ,
24
29
Extrapolate :: Error ,
25
30
)
26
31
. unwrap ( ) ;
27
- interp_0d_multi. interpolate ( & [ ] ) . unwrap ( ) ;
32
+ interp_0d_multi. interpolate ( black_box ( & [ ] ) ) . unwrap ( ) ;
28
33
}
29
34
30
35
#[ allow( non_snake_case) ]
31
36
/// 1-D interpolation (hardcoded)
32
37
fn benchmark_1D ( ) {
33
- let seed = 1234567890 ;
34
- let mut rng = StdRng :: seed_from_u64 ( seed) ;
35
- let grid_data: Vec < f64 > = ( 0 ..100 ) . map ( |x| x as f64 ) . collect ( ) ;
38
+ let mut rng = StdRng :: seed_from_u64 ( RANDOM_SEED ) ;
39
+ let grid_data: Array1 < f64 > = ( 0 ..100 ) . map ( |x| x as f64 ) . collect ( ) ;
36
40
// Generate interpolator data (same as N-D benchmark)
37
- let values_data: Vec < f64 > = ( 0 .. 100 ) . map ( |_| rng . random :: < f64 > ( ) ) . collect ( ) ;
41
+ let values_data = Array1 :: random_using ( 100 , Uniform :: new ( 0. , 1. ) , & mut rng ) ;
38
42
// Create a 1-D interpolator with 100 data points
39
43
let interp_1d = Interp1D :: new ( grid_data, values_data, Linear , Extrapolate :: Error ) . unwrap ( ) ;
40
44
// Sample 1,000 points
41
- let points: Vec < f64 > = ( 0 ..1_000 ) . map ( |_| rng. random :: < f64 > ( ) * 99. ) . collect ( ) ;
45
+ let points: Vec < f64 > = ( 0 ..1_000 ) . map ( |_| rng. gen :: < f64 > ( ) * 99. ) . collect ( ) ;
42
46
for point in points {
43
- interp_1d. interpolate ( & [ point] ) . unwrap ( ) ;
47
+ interp_1d. interpolate ( black_box ( & [ point] ) ) . unwrap ( ) ;
44
48
}
45
49
}
46
50
47
51
#[ allow( non_snake_case) ]
48
52
/// 1-D interpolation (multilinear interpolator)
49
53
fn benchmark_1D_multi ( ) {
50
- let seed = 1234567890 ;
51
- let mut rng = StdRng :: seed_from_u64 ( seed) ;
54
+ let mut rng = StdRng :: seed_from_u64 ( RANDOM_SEED ) ;
52
55
// Generate interpolator data (same as hardcoded benchmark)
53
- let grid_data: Vec < f64 > = ( 0 ..100 ) . map ( |x| x as f64 ) . collect ( ) ;
54
- let values_data: Vec < f64 > = ( 0 .. 100 ) . map ( |_| rng. random :: < f64 > ( ) ) . collect ( ) ;
56
+ let grid_data: Array1 < f64 > = ( 0 ..100 ) . map ( |x| x as f64 ) . collect ( ) ;
57
+ let values_data = Array1 :: random_using ( 100 , Uniform :: new ( 0. , 1. ) , & mut rng) . into_dyn ( ) ;
55
58
// Create an N-D interpolator with 100x100 data (10,000 points)
56
- let interp_1d_multi = InterpND :: new (
57
- vec ! [ grid_data] ,
58
- ArrayD :: from_shape_vec ( IxDyn ( & [ 100 ] ) , values_data) . unwrap ( ) ,
59
- Linear ,
60
- Extrapolate :: Error ,
61
- )
62
- . unwrap ( ) ;
59
+ let interp_1d_multi =
60
+ InterpND :: new ( vec ! [ grid_data] , values_data, Linear , Extrapolate :: Error ) . unwrap ( ) ;
63
61
// Sample 1,000 points
64
- let points: Vec < f64 > = ( 0 ..1_000 ) . map ( |_| rng. random :: < f64 > ( ) * 99. ) . collect ( ) ;
62
+ let points: Vec < f64 > = ( 0 ..1_000 ) . map ( |_| rng. gen :: < f64 > ( ) * 99. ) . collect ( ) ;
65
63
for point in points {
66
- interp_1d_multi. interpolate ( & [ point] ) . unwrap ( ) ;
64
+ interp_1d_multi. interpolate ( black_box ( & [ point] ) ) . unwrap ( ) ;
67
65
}
68
66
}
69
67
70
68
#[ allow( non_snake_case) ]
71
69
/// 2-D interpolation (hardcoded)
72
70
fn benchmark_2D ( ) {
73
- let seed = 1234567890 ;
74
- let mut rng = StdRng :: seed_from_u64 ( seed) ;
75
- let grid_data: Vec < f64 > = ( 0 ..100 ) . map ( |x| x as f64 ) . collect ( ) ;
76
- // Generate interpolator data (same as N-D benchmark) and arrange into `Vec<Vec<f64>>`
77
- let values_data: Vec < f64 > = ( 0 ..10_000 ) . map ( |_| rng. random :: < f64 > ( ) ) . collect ( ) ;
78
- let values_data: Vec < Vec < f64 > > = ( 0 ..100 )
79
- . map ( |x| values_data[ ( 100 * x) ..( 100 + 100 * x) ] . into ( ) )
80
- . collect ( ) ;
71
+ let mut rng = StdRng :: seed_from_u64 ( RANDOM_SEED ) ;
72
+ let grid_data: Array1 < f64 > = ( 0 ..100 ) . map ( |x| x as f64 ) . collect ( ) ;
73
+ let values_data = Array2 :: random_using ( ( 100 , 100 ) , Uniform :: new ( 0. , 1. ) , & mut rng) ;
81
74
// Create a 2-D interpolator with 100x100 data (10,000 points)
82
75
let interp_2d = Interp2D :: new (
83
- grid_data. clone ( ) ,
84
- grid_data. clone ( ) ,
85
- values_data,
76
+ grid_data. view ( ) ,
77
+ grid_data. view ( ) ,
78
+ values_data. view ( ) ,
86
79
Linear ,
87
80
Extrapolate :: Error ,
88
81
)
89
82
. unwrap ( ) ;
90
83
// Sample 1,000 points
91
84
let points: Vec < Vec < f64 > > = ( 0 ..1_000 )
92
- . map ( |_| vec ! [ rng. random :: <f64 >( ) * 99. , rng. random :: <f64 >( ) * 99. ] )
85
+ . map ( |_| vec ! [ rng. gen :: <f64 >( ) * 99. , rng. gen :: <f64 >( ) * 99. ] )
93
86
. collect ( ) ;
94
87
for point in points {
95
- interp_2d. interpolate ( & point) . unwrap ( ) ;
88
+ interp_2d. interpolate ( black_box ( & point) ) . unwrap ( ) ;
96
89
}
97
90
}
98
91
99
92
#[ allow( non_snake_case) ]
100
93
/// 2-D interpolation (multilinear interpolator)
101
94
fn benchmark_2D_multi ( ) {
102
- let seed = 1234567890 ;
103
- let mut rng = StdRng :: seed_from_u64 ( seed) ;
95
+ let mut rng = StdRng :: seed_from_u64 ( RANDOM_SEED ) ;
104
96
// Generate interpolator data (same as hardcoded benchmark)
105
- let grid_data: Vec < f64 > = ( 0 ..100 ) . map ( |x| x as f64 ) . collect ( ) ;
106
- let values_data: Vec < f64 > = ( 0 .. 10_000 ) . map ( |_| rng. random :: < f64 > ( ) ) . collect ( ) ;
97
+ let grid_data: Array1 < f64 > = ( 0 ..100 ) . map ( |x| x as f64 ) . collect ( ) ;
98
+ let values_data = Array2 :: random_using ( ( 100 , 100 ) , Uniform :: new ( 0. , 1. ) , & mut rng) . into_dyn ( ) ;
107
99
// Create an N-D interpolator with 100x100 data (10,000 points)
108
100
let interp_2d_multi = InterpND :: new (
109
- vec ! [ grid_data. clone ( ) , grid_data. clone ( ) ] ,
110
- ArrayD :: from_shape_vec ( IxDyn ( & [ 100 , 100 ] ) , values_data) . unwrap ( ) ,
101
+ vec ! [ grid_data. view ( ) , grid_data. view ( ) ] ,
102
+ values_data. view ( ) ,
111
103
Linear ,
112
104
Extrapolate :: Error ,
113
105
)
114
106
. unwrap ( ) ;
115
107
// Sample 1,000 points
116
108
let points: Vec < Vec < f64 > > = ( 0 ..1_000 )
117
- . map ( |_| vec ! [ rng. random :: <f64 >( ) * 99. , rng. random :: <f64 >( ) * 99. ] )
109
+ . map ( |_| vec ! [ rng. gen :: <f64 >( ) * 99. , rng. gen :: <f64 >( ) * 99. ] )
118
110
. collect ( ) ;
119
111
for point in points {
120
- interp_2d_multi. interpolate ( & point) . unwrap ( ) ;
112
+ interp_2d_multi. interpolate ( black_box ( & point) ) . unwrap ( ) ;
121
113
}
122
114
}
123
115
124
116
#[ allow( non_snake_case) ]
125
117
/// 3-D interpolation (hardcoded)
126
118
fn benchmark_3D ( ) {
127
- let seed = 1234567890 ;
128
- let mut rng = StdRng :: seed_from_u64 ( seed) ;
129
- let grid_data: Vec < f64 > = ( 0 ..100 ) . map ( |x| x as f64 ) . collect ( ) ;
119
+ let mut rng = StdRng :: seed_from_u64 ( RANDOM_SEED ) ;
120
+ let grid_data: Array1 < f64 > = ( 0 ..100 ) . map ( |x| x as f64 ) . collect ( ) ;
130
121
// Generate interpolator data (same as N-D benchmark) and arrange into `Vec<Vec<Vec<f64>>>`
131
- let values_data: Vec < f64 > = ( 0 ..1_000_000 ) . map ( |_| rng. random :: < f64 > ( ) ) . collect ( ) ;
132
- let values_data: Vec < Vec < Vec < f64 > > > = ( 0 ..100 )
133
- . map ( |x| {
134
- ( 0 ..100 )
135
- . map ( |y| values_data[ ( 100 * ( y + 100 * x) ) ..( 100 + 100 * ( y + 100 * x) ) ] . into ( ) )
136
- . collect ( )
137
- } )
138
- . collect ( ) ;
122
+ let values_data = Array3 :: random_using ( ( 100 , 100 , 100 ) , Uniform :: new ( 0. , 1. ) , & mut rng) ;
139
123
// Create a 3-D interpolator with 100x100x100 data (1,000,000 points)
140
124
let interp_3d = Interp3D :: new (
141
- grid_data. clone ( ) ,
142
- grid_data. clone ( ) ,
143
- grid_data. clone ( ) ,
144
- values_data,
125
+ grid_data. view ( ) ,
126
+ grid_data. view ( ) ,
127
+ grid_data. view ( ) ,
128
+ values_data. view ( ) ,
145
129
Linear ,
146
130
Extrapolate :: Error ,
147
131
)
@@ -150,29 +134,29 @@ fn benchmark_3D() {
150
134
let points: Vec < Vec < f64 > > = ( 0 ..1_000 )
151
135
. map ( |_| {
152
136
vec ! [
153
- rng. random :: <f64 >( ) * 99. ,
154
- rng. random :: <f64 >( ) * 99. ,
155
- rng. random :: <f64 >( ) * 99. ,
137
+ rng. gen :: <f64 >( ) * 99. ,
138
+ rng. gen :: <f64 >( ) * 99. ,
139
+ rng. gen :: <f64 >( ) * 99. ,
156
140
]
157
141
} )
158
142
. collect ( ) ;
159
143
for point in points {
160
- interp_3d. interpolate ( & point) . unwrap ( ) ;
144
+ interp_3d. interpolate ( black_box ( & point) ) . unwrap ( ) ;
161
145
}
162
146
}
163
147
164
148
#[ allow( non_snake_case) ]
165
149
/// 3-D interpolation (multilinear interpolator)
166
150
fn benchmark_3D_multi ( ) {
167
- let seed = 1234567890 ;
168
- let mut rng = StdRng :: seed_from_u64 ( seed) ;
151
+ let mut rng = StdRng :: seed_from_u64 ( RANDOM_SEED ) ;
169
152
// Generate interpolator data (same as hardcoded benchmark)
170
- let grid_data: Vec < f64 > = ( 0 ..100 ) . map ( |x| x as f64 ) . collect ( ) ;
171
- let values_data: Vec < f64 > = ( 0 ..1_000_000 ) . map ( |_| rng. random :: < f64 > ( ) ) . collect ( ) ;
153
+ let grid_data: Array1 < f64 > = ( 0 ..100 ) . map ( |x| x as f64 ) . collect ( ) ;
154
+ let values_data =
155
+ Array3 :: random_using ( ( 100 , 100 , 100 ) , Uniform :: new ( 0. , 1. ) , & mut rng) . into_dyn ( ) ;
172
156
// Create an N-D interpolator with 100x100x100 data (1,000,000 points)
173
157
let interp_3d_multi = InterpND :: new (
174
- vec ! [ grid_data. clone ( ) , grid_data. clone ( ) , grid_data. clone ( ) ] ,
175
- ArrayD :: from_shape_vec ( IxDyn ( & [ 100 , 100 , 100 ] ) , values_data) . unwrap ( ) ,
158
+ vec ! [ grid_data. view ( ) , grid_data. view ( ) , grid_data. view ( ) ] ,
159
+ values_data. view ( ) ,
176
160
Linear ,
177
161
Extrapolate :: Error ,
178
162
)
@@ -181,14 +165,14 @@ fn benchmark_3D_multi() {
181
165
let points: Vec < Vec < f64 > > = ( 0 ..1_000 )
182
166
. map ( |_| {
183
167
vec ! [
184
- rng. random :: <f64 >( ) * 99. ,
185
- rng. random :: <f64 >( ) * 99. ,
186
- rng. random :: <f64 >( ) * 99. ,
168
+ rng. gen :: <f64 >( ) * 99. ,
169
+ rng. gen :: <f64 >( ) * 99. ,
170
+ rng. gen :: <f64 >( ) * 99. ,
187
171
]
188
172
} )
189
173
. collect ( ) ;
190
174
for point in points {
191
- interp_3d_multi. interpolate ( & point) . unwrap ( ) ;
175
+ interp_3d_multi. interpolate ( black_box ( & point) ) . unwrap ( ) ;
192
176
}
193
177
}
194
178
0 commit comments