diff --git a/benches/rayon.rs b/benches/rayon.rs new file mode 100644 index 00000000000..5195aafe8aa --- /dev/null +++ b/benches/rayon.rs @@ -0,0 +1,61 @@ +#![feature(test)] + +extern crate test; +extern crate rand; +extern crate rayon; + +use test::{black_box, Bencher}; + +use rand::{Rng, NewRng, XorShiftRng, thread_rng}; +use rand::distributions::*; + +use rayon::iter::{ParallelIterator, IntoParallelIterator}; + +#[bench] +fn gen_100_000_sequential(b: &mut Bencher) { + let mut rng = XorShiftRng::new(); + + b.iter(|| { + let vec: Vec = (0..100_000) + .into_iter() + .map(|_| { rng.gen::() }) + .collect(); + black_box(vec[0]); + }); + b.bytes = 100_000 * 4; +} + +#[bench] +fn gen_100_000_sample_iter(b: &mut Bencher) { + let mut rng = XorShiftRng::new(); + + b.iter(|| { + let vec: Vec = rng.sample_iter(&Standard).take(100_000).collect(); + black_box(vec[0]); + }); + b.bytes = 100_000 * 4; +} + +#[bench] +fn gen_100_000_parallel(b: &mut Bencher) { + let mut rng = XorShiftRng::new(); + + b.iter(|| { + let vec: Vec = Standard.sample_par_iter(&mut rng, 100_000).collect(); + black_box(vec[0]); + }); + b.bytes = 100_000 * 4; +} + +#[bench] +fn gen_100_000_thread_local(b: &mut Bencher) { + b.iter(|| { + + let vec: Vec = (0..100_000) + .into_par_iter() + .map(|_| { thread_rng().gen::() }) + .collect(); + black_box(vec[0]); + }); + b.bytes = 100_000 * 4; +} diff --git a/src/distributions/rayon.rs b/src/distributions/rayon.rs index 21f0ba05c0d..b4a9330be5d 100644 --- a/src/distributions/rayon.rs +++ b/src/distributions/rayon.rs @@ -145,13 +145,16 @@ impl<'a, D, R, T> Producer for DistProducer<'a, D, R, T> assert!(index <= self.amount); // Create a new PRNG of the same type, by seeding it with this PRNG. // `from_rng` should never fail. - let new = DistProducer { + let mut new = DistProducer { distr: self.distr, amount: self.amount - index, rng: R::from_rng(&mut self.rng).unwrap(), phantom: ::core::marker::PhantomData, }; self.amount = index; + + // emulate an expensive jump operation + for _ in 0..150 { let _ = new.rng.next_u32(); } (self, new) } diff --git a/src/thread_rng.rs b/src/thread_rng.rs index 1b93a8c2107..93f5426785b 100644 --- a/src/thread_rng.rs +++ b/src/thread_rng.rs @@ -13,8 +13,8 @@ use std::cell::UnsafeCell; use std::rc::Rc; -use {RngCore, CryptoRng, SeedableRng, EntropyRng}; -use prng::hc128::Hc128Core; +use {RngCore, CryptoRng, SeedableRng, EntropyRng, NewRng}; +use prng::XorShiftRng; use {Distribution, Standard, Rng, Error}; use reseeding::ReseedingRng; @@ -53,18 +53,12 @@ const THREAD_RNG_RESEED_THRESHOLD: u64 = 32*1024*1024; // 32 MiB /// [`thread_rng`]: fn.thread_rng.html #[derive(Clone, Debug)] pub struct ThreadRng { - rng: Rc>>, + rng: Rc>, } thread_local!( - static THREAD_RNG_KEY: Rc>> = { - let mut entropy_source = EntropyRng::new(); - let r = Hc128Core::from_rng(&mut entropy_source).unwrap_or_else(|err| - panic!("could not initialize thread_rng: {}", err)); - let rng = ReseedingRng::new(r, - THREAD_RNG_RESEED_THRESHOLD, - entropy_source); - Rc::new(UnsafeCell::new(rng)) + static THREAD_RNG_KEY: Rc> = { + Rc::new(UnsafeCell::new(XorShiftRng::new())) } );