How can I, using stable rust, mutably iterate over a random shuffle?

This is a follow up to a previous question.

I ended up taking the previous solution and updating it to use Rayon for parallel computation. The code now looks like this

all_orgs.par_chunks_mut(48).for_each(|chunk: &mut [Organism]|{
    for i in 0 .. chunk.len() {
        let (left, others) = chunk.split_at_mut(i);
        let (middle, right) = others.split_at_mut(1);
        let org1 = &mut middle[0];
        //process left
        for org2 in left {
            single_match_up(org1, org2);
        }
        //process right
        for org2 in right {
            single_match_up(org1, org2);
        }
    }
});

The idea is that organisms are placed into groups (chunks) and each organism competes with each other organism (twice) within a chunk.

Now I want to randomly assign organisms to chunks. It seems to me that shuffling a vector of references is goin to be cheaper than shiffling a vector of structs so I will start by creating a Vec<&mut Organism> then shuffle it, then process it similarly to above. The result is this:

let mut org_refs = all_orgs.iter_mut().collect_vec();
org_refs.shuffle(&mut rng);

org_refs.par_chunks_mut(48).for_each(|chunk| {
    for i in 0 .. chunk.len() {
        let (left, others) = chunk.split_at_mut(i);
        let (middle, right) = others.split_at_mut(1);
        let org1 = &mut middle[0];
        //process left
        for org2 in left {
            single_match_up(org1, org2);
        }
        //process right
        for org2 in right {
            single_match_up(org1, org2);
        }
    }
});

This compiles, runs, and seems to produce the correct result. But what seems strange is that now I am dealing with references to references. For example, the type of left is &mut [&mut Organism] and the type of org1 is &mut &mut Organism.

Is this really the right way of doing this? Presumably it would be more efficient to remove a layer of referencing.

PS: I see the latest answer on the previous question recommends a nightly feature which seems like it could do the job here. But for now I am interested in stable rust while I learn the language.

Have you benchmarked this? Pointer chasing is terribly expensive, I wouldn't be surprised if shuffling your organisms directly is a lot faster that having to double dereference in your hot path.

1 Like

You can very easily remove it, you'll just have to shuffle the original all_orgs vector/slice as opposed to shuffling a new vector of references to its elements. It is a tradeoff: you're adding a layer of indirection to avoid doing potentially expensive work, but then you'll be paying the cost of that indirection when you access the elements.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.