Home > front end >  |Rust| What's the most performant way of initializing a BIG and RANDOMIZED array?
|Rust| What's the most performant way of initializing a BIG and RANDOMIZED array?

Time:10-23

*Note i'm using the 'rand' crate.

I'm new to rust and through some research and testing I was able to find two solutions to this:

#1: This on initializes an array and then populates it with random values:

type RandomArray = [usize; 900]; 

pub fn make_array() -> RandomArray {

    let mut rng = thread_rng();
    
    let mut arr: RandomArray = [0; 900];
        
    for i in 0..900 {
        //I need a range of random values!
        arr[i] = rng.gen_range(0..900)
    }

    arr
}

#2: This one initializes an array, it populates it with values from 0 to 900 and then shuffles it:

type RandomArray = [usize; 900]; 

pub fn make_shuffled_array() -> RandomArray  {
    let mut rng = thread_rng();
    
    let mut arr: RandomArray = [0; 900];
        
    for i in 0..900 {
        arr[i] = i;
    }

    arr.shuffle(&mut rng);

    arr
}

Through my testing, it seems like '#1' is slower but more consistent. But none of these actually initializes the array with the random range of numbers.

Both of these seem to be pretty fast and simple, however, I'm sure that there is an even faster way of doing this.

CodePudding user response:

When it comes to generating "random" data I don't know what exactly you need. To me #1 seems like it does what you describe. If you want to have random range bounds you can generate them first and only then use gen_range.

When it comes to the performance #1 should be faster, since it walks the whole array twice (once in the creation, and once in the initialization), but #2 walks it three times (creation, initialization and shuffling). You can't really do anything about the initialization part, but you can skip the "creation" part.

Rust requires that all data is initialized. Therefore you must specify what elements are in your array at the beginning, event though you will overwrite it on the next step. To opt-out from this you can use rust's special type MaybeUninit. I encourage you to read carefully it's documentation, since using it is very unsafe, but here you have a simple example of how you could use it.

use std::mem::{transmute, MaybeUninit};

fn get_random() -> usize {
    // chosen by fair dice roll.
    // https://xkcd.com/221/
    4
}

const N: usize = 900;

fn make_array() -> [usize; N] {
    // Unstable MaybeUninit::uninit_array
    let mut array: [MaybeUninit<usize>; N] =
        unsafe { MaybeUninit::<[MaybeUninit<usize>; N]>::uninit().assume_init() };

    for x in &mut array {
        x.write(get_random());
    }

    // Acts like unstable MaybeUninit::array_assume_init
    let array: [usize; N] = unsafe { transmute(array) };

    array
}
  • Related