I need to assign the values of one vector to another, like:
let mut vec_a: Vec<f64> = vec![0.1; 100];
let mut vec_b: Vec<f64> = vec![0.1; 100];
// Do something with vec_a. Real vectors are ~1e6 long
unsafe {
vec_b = Vec::from_raw_parts(&vec_a, vec_a.len(), vec_a.len());
}
I'm looking for help to answer these questions:
Is there a more efficient and safer way of doing this?
Why it has to be under unsafe
code if everything is being handled by the same application/code?
If it is the correct way, will it have a difference if instead of Vec::from_raw_parts
use std::slice::from_raw_parts
?
The reason behind this need is to avoid copying the data. This may happen with a high frequency and every time, one vector will be the storage to keep track of a best solution (let's say vec_a
), the other one will be exploring other solutions. When a better solution is found, the only thing that needs to be changed is the pointer
to the vector, now vec_a
stores the best solution that was found in vec_b
and vec_b
can keep exploring different solutions.
CodePudding user response:
The naive answer is fairly performant. A simple assignment (best_solution = solution
) doesn't do a deep copy of the elements, it only transfers ownership and destroys the source.
let mut best_solution = vec![0.1; 100];
loop {
let solution = generate_solution();
if solution > best_solution {
best_solution = solution;
}
}
One thing you can do to make it more performant is to reduce allocations by using a persistent vec as scratch space (you may be getting at this in the code in your post). In that case you would use std::mem::swap
to avoid destroying the scratch vec.
let mut best_solution = vec![0.1; 100];
let mut scratch_solution = vec![0.1; 100];
loop {
generate_solution(&mut scratch_solution);
if scratch_solution > best_solution {
std::mem::swap(&mut best_solution, &mut scratch_solution);
}
}
CodePudding user response:
You should use just swap and moves for this. Check this test that shows that swapping vectors only change pointers:
fn main() {
let mut v1 = vec![0; 100];
let mut v2 = vec![0; 100];
let old_ptr1 = v1.as_ptr();
let old_ptr2 = v2.as_ptr();
std::mem::swap(&mut v1, &mut v2);
assert_eq!(old_ptr1, v2.as_ptr());
assert_eq!(old_ptr2, v1.as_ptr());
}
CodePudding user response:
Hard to tell your intentions, but if you want to move all the values of source vector into a destination vector without loosing content of destination, then you can swap vectors contents without copying data. E.g.
fn main() {
let mut vec_a: Vec<f64> = vec![0.1; 100];
let mut vec_b: Vec<f64> = vec![0.2; 100];
println!("{}", vec_a[0]); // 0.1
println!("{}", vec_b[0]); // 0.2
let (mut vec_a, mut vec_b) = (vec_b, vec_a);
println!("{}", vec_a[0]); // 0.2
println!("{}", vec_b[0]); // 0.1
}