8
8
9
9
//! Implement benchmarks for uniform distributions over integer types
10
10
11
+ #![ cfg_attr( feature = "simd_support" , feature( portable_simd) ) ]
12
+
11
13
use core:: time:: Duration ;
12
14
use criterion:: { criterion_group, criterion_main, BenchmarkId , Criterion } ;
13
15
use rand:: distr:: uniform:: { SampleRange , Uniform } ;
14
16
use rand:: prelude:: * ;
15
17
use rand_chacha:: ChaCha8Rng ;
16
18
use rand_pcg:: { Pcg32 , Pcg64 } ;
19
+ #[ cfg( feature = "simd_support" ) ]
20
+ use std:: simd:: { num:: SimdUint , Simd } ;
17
21
18
22
const WARM_UP_TIME : Duration = Duration :: from_millis ( 1000 ) ;
19
23
const MEASUREMENT_TIME : Duration = Duration :: from_secs ( 3 ) ;
@@ -29,22 +33,46 @@ macro_rules! sample {
29
33
( ( x >> bits) * ( x & mask) ) as $T
30
34
} } ;
31
35
36
+ ( @range $T: ty, $U: ty, $len: tt, $rng: ident) => { {
37
+ let bits = ( <$T>:: BITS / 2 ) ;
38
+ let mask = Simd :: splat( ( 1 as $U) . wrapping_neg( ) >> bits) ;
39
+ let bits = Simd :: splat( bits as $U) ;
40
+ let x = $rng. random:: <Simd <$U, $len>>( ) ;
41
+ ( ( x >> bits) * ( x & mask) ) . cast( )
42
+ } } ;
43
+
44
+ ( @MIN $T: ty, 1 ) => {
45
+ <$T>:: MIN
46
+ } ;
47
+
48
+ ( @MIN $T: ty, $len: tt) => {
49
+ Simd :: <$T, $len>:: splat( <$T>:: MIN )
50
+ } ;
51
+
52
+ ( @wrapping_add $lhs: expr, $rhs: expr, 1 ) => {
53
+ $lhs. wrapping_add( $rhs)
54
+ } ;
55
+
56
+ ( @wrapping_add $lhs: expr, $rhs: expr, $len: tt) => {
57
+ ( $lhs + $rhs)
58
+ } ;
59
+
32
60
( $R: ty, $T: ty, $U: ty, $len: tt, $g: expr) => {
33
61
$g. bench_function( BenchmarkId :: new( stringify!( $R) , "single" ) , |b| {
34
62
let mut rng = <$R>:: from_rng( & mut rand:: rng( ) ) ;
35
63
let range = sample!( @range $T, $U, $len, rng) ;
36
- let low = <$T> :: MIN ;
37
- let high = low . wrapping_add ( range) ;
64
+ let low = sample! ( @ MIN $T , $len ) ;
65
+ let high = sample! ( @wrapping_add low , range, $len ) ;
38
66
39
67
b. iter( || ( low..=high) . sample_single( & mut rng) ) ;
40
68
} ) ;
41
69
42
70
$g. bench_function( BenchmarkId :: new( stringify!( $R) , "distr" ) , |b| {
43
71
let mut rng = <$R>:: from_rng( & mut rand:: rng( ) ) ;
44
72
let range = sample!( @range $T, $U, $len, rng) ;
45
- let low = <$T> :: MIN ;
46
- let high = low . wrapping_add ( range) ;
47
- let dist = Uniform :: <$T> :: new_inclusive( <$T> :: MIN , high) . unwrap( ) ;
73
+ let low = sample! ( @ MIN $T , $len ) ;
74
+ let high = sample! ( @wrapping_add low , range, $len ) ;
75
+ let dist = Uniform :: new_inclusive( low , high) . unwrap( ) ;
48
76
49
77
b. iter( || dist. sample( & mut rng) ) ;
50
78
} ) ;
@@ -74,6 +102,20 @@ fn sample(c: &mut Criterion) {
74
102
sample ! ( c, i32 , u32 , 1 ) ;
75
103
sample ! ( c, i64 , u64 , 1 ) ;
76
104
sample ! ( c, i128 , u128 , 1 ) ;
105
+ #[ cfg( feature = "simd_support" ) ]
106
+ sample ! ( c, u8 , u8 , 8 ) ;
107
+ #[ cfg( feature = "simd_support" ) ]
108
+ sample ! ( c, u8 , u8 , 16 ) ;
109
+ #[ cfg( feature = "simd_support" ) ]
110
+ sample ! ( c, u8 , u8 , 32 ) ;
111
+ #[ cfg( feature = "simd_support" ) ]
112
+ sample ! ( c, u8 , u8 , 64 ) ;
113
+ #[ cfg( feature = "simd_support" ) ]
114
+ sample ! ( c, i16 , u16 , 8 ) ;
115
+ #[ cfg( feature = "simd_support" ) ]
116
+ sample ! ( c, i16 , u16 , 16 ) ;
117
+ #[ cfg( feature = "simd_support" ) ]
118
+ sample ! ( c, i16 , u16 , 32 ) ;
77
119
}
78
120
79
121
criterion_group ! {
0 commit comments