rust-random / rngs

Extra RNGs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Example usage of `xorshiro` jump method

YuhanLiin opened this issue · comments

Many of the xorshiro generators, such as Xorshiro256Plus, have a method called jump that allows the RNG to generate different sequences in parallel applications. However, I'm not sure how to actually use jump for parallel computing, and the examples don't really show much. Can someone provide an example of the jump API being used in parallel computing?

The xorshift crate has an example with Rust's thread::spawn: https://docs.rs/xorshift/latest/xorshift/#parallelism

I don't know of a clean way to do this with rayon since for_each/etc_init don't allow FnMut. Perhaps some custom Clone hack with for_each_with is possible (but without mutable access? idk).

Though I suppose something like this is possible:

let mut rng = Xoshiro256PlusPlus::from_entropy();
let mut rngs: Vec<_> = data
    .iter()
    .map(|_| { rng.jump(); rng.clone() })
    .collect();

data.par_iter()
    .zip_eq(&mut rngs)
    .for_each(|(elem, rng)| todo!());

But that has significant constraints

The xorshift algorithm's jump API takes a usize, which I assume controls how many jumps are done. The jump call in Xoshiro doesn't take this parameter, so how would I replicate the effect of the usize param? Do I just jump in a for loop?

Without Copy something like this works:

let seed = thread_rng().gen();
for i in 0..17 {
    threads.push(std::thread::spawn(move || {
        let mut r = Xoshiro256PlusPlus::from_seed(seed);
        for _ in 0..i {
            r.jump();
        }

but that's a lot of repeated jumps. collecting the rngs like #38 (comment) might be better

Would it be cheaper to just construct multiple instances of the RNG with difference seeds? Xoshiro initialization time is supposedly cheap.

I think using LXM generators and a custom Clone implementation with rayon::map_with is probably the state-of-the-art right now and also more convenient.

Turns out LXM generators still require mutable access to some parent RNG but there might be a safe way to dynamically seed them with thread_rng.
I wonder if you could use a Mutex or Arc or something in a custom Clone? Otherwise I don't know if a mutable version of rayon::map_with is possible but it would be very helpful

I think I understand what I need to do. Thanks for your help.