Using self or parent inside the closure

Hi All,

When I run my code, it takes more time. So, I thought I will optimise it. I changed iter to par_iter wherever possible. I am stuck in using the self or parent struct. My similar (sample) code is below,

fn main() {
    let s1 = MyStruct{offset: 5.0, val: vec![5.0,6.0,7.0]};
    let s2 = MyStruct{offset: 4.0, val: vec![5.0,6.0,7.0]};
    let mut all_s = vec![];
    all_s.push(s1);
    all_s.push(s2);
    offsety(&mut all_s);
}

fn offsety(all_s: &mut Vec<MyStruct>) {
    all_s.par_iter_mut().for_each(|s| {
        let mut val = &mut s.val;
        val.par_iter_mut().for_each(|v| {
            let off = s.add();
            println!("{}", off)
            //*v = *v + off;
        });
    });
}

struct MyStruct {
    offset: f32,
    val: Vec<f32>
}

impl MyStruct {
    fn add(&self) -> f32 {
        return self.offset + 1.0;
    }
}

second borrow occurs due to use of s in closure

In one of the forum the suggestion was to use Mutex. I was seeing if it is possible to avoid adding Mutex because I dont see a point in locking if I am going to do read-only.

This is the partial borrow problem that has been discussed in a recent thread: Why can't I change a reference? - #16 by GRASBOCK The discussion contains a lot of info and suggestions which might be helpful.

In the (possibly contrived) example provided, this can be fixed in the following ways:

  1. Hoist the call to s.add() outside of the inner closure. E.g. call s.add() before iterating s.val
  2. Split the MyStruct type so you do not need to take a shared reference while iterating over an exclusive reference.
  3. Use an internally mutable type with .par_iter() (Effectively comes down to using a mutex, which you explicitly said you are not interested in...)

playground showing solutions 1 and 2.

Thanks @parasyte - However, in my case I also have to pass the v as a fuction parameter to s.add(). Something like, s.add(v). Sorry for not being clear. So I think I should avoid par_iter

However, after removing par_iter, I am getting below message

cannot borrow *self as immutable because it is also borrowed as mutable

I thought why cant I make self as an argument and below is my code,

MyStruct::add(&self, v);

self.add(v) is just syntactic sugar for MyStruct::add(&self, v).

I don't understand how you expect your add method to accept a vector as an input argument; presumably it is not consuming the vector. Do you want to pass the vector by reference? And to what end? Can you reformulate the problem using index operations instead of borrows?

Okay... Then I will re change the example code.

In my code I have a struct which has multiple hashmaps. Let us say HashMap1 and HashMap2. Based on the value in HashMap2, I want something to happen in HashMap1.

Algorithm is something like this (I am not sure if there is any error),

for each in MyStructs {
let v3 = 0;
    for (k1,v1) in self.HashMap1 {
         for (k2, v2) in v1 {
              let x = self.myfunc(k2);
              // Do some computation
              let v3 = v1 + x;
         }
    }
MyStruct.HaspMap2.insert(k1,v3);
}

Sorry, if it is a mix of other languages and Rust
Sorry for multiple edits

I think I have reproduced the issue. Note that it is not what you suggested

fn main() {
    println!("hoisted:");
    hoisted::example();
}

mod hoisted {
    use rayon::prelude::*;

    pub struct MyStruct {
        offset: f32,
        val: Vec<f32>,
        final_val: Vec<f32>
    }
    
    impl MyStruct {
        fn add(&self, v: f32) -> f32 {
            return v + self.offset + 1.0;
        }
    }
    
    pub fn offsety(all_s: &mut Vec<MyStruct>) {
        all_s.par_iter_mut().for_each(|s| {
            
            s.val.par_iter_mut().for_each(|v| {
                let off = s.add(*v);
                println!("{}", off);
                s.final_val.push(off);
            });
        });
    }

    pub fn example() {
        let s1 = MyStruct{offset: 5.0, val: vec![5.0,6.0,7.0], final_val: vec![]};
        let s2 = MyStruct{offset: 4.0, val: vec![5.0,6.0,7.0], final_val: vec![]};
        let mut all_s = vec![s1, s2];
        offsety(&mut all_s);
    }
}

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.