Skip to content

Immutable reference to ArrayRef is not Sync #1569

@EthanD11

Description

@EthanD11

I am writing a code for feature tracking in rust and I would like to parallelize my code over the features. For this I need to have the images shared across the threads, however I cannot do so when the type of the images are &ArrayRef2, however it works if the type of the images are &ArrayBase<S, Ix2> with the required trait bounds .

Below is a minimal reproducible example:

use ndarray::{ArrayBase, ArrayRef2, Data, Ix2, ScalarOperand, Zip, arr2};
use num_traits::{Float, FromPrimitive};


// Fails to compile
pub fn track_level<A>(
    image_host: &ArrayRef2<A>, 
    image_target: &ArrayRef2<A>,
    keypoints_host: &ArrayRef2<A>,
    keypoints_target: &mut ArrayRef2<A>
)
where 
    A: Float + Send + Sync + ScalarOperand + FromPrimitive
{
    Zip::from(keypoints_host.rows()).and(keypoints_target.rows_mut()).par_for_each(
        |kp_host, mut kp_target| 
        {
            let t = arr2(&[[image_host.mean().unwrap()], [image_target.mean().unwrap()]]);
            kp_target.assign(&(&kp_host + &t));
        }
    );
    
}

// Compiles succesfully
pub fn track_level_array_base<A, SH, ST>(
    image_host: &ArrayBase<SH, Ix2>, 
    image_target: &ArrayBase<ST, Ix2>,
    keypoints_host: &ArrayRef2<A>,
    keypoints_target: &mut ArrayRef2<A>
)
where 
    A: Float + Send + Sync + ScalarOperand + FromPrimitive,
    SH: Data<Elem = A> + Send + Sync,
    ST: Data<Elem = A> + Send + Sync
{
    Zip::from(keypoints_host.rows()).and(keypoints_target.rows_mut()).par_for_each(
        |kp_host, mut kp_target| 
        {
            let t = arr2(&[[image_host.mean().unwrap()], [image_target.mean().unwrap()]]);
            kp_target.assign(&(&kp_host + &t));
        }
    );
}

The compiler error I get is the following:

error[E0277]: `NonNull<A>` cannot be shared between threads safely
    --> src/patch_tracker/test.rs:16:9
     |
  15 |       Zip::from(keypoints_host.rows()).and(keypoints_target.rows_mut()).par_for_each(
     |                                                                         ------------ required by a bound introduced by this call
  16 |           |kp_host, mut kp_target| 
     |           ^-----------------------
     |           |
     |  _________within this `{closure@src/patch_tracker/test.rs:16:9: 16:33}`
     | |
  17 | |         {
  18 | |             let t = arr2(&[[image_host.mean().unwrap()], [image_target.mean().unwrap()]]);
  19 | |             kp_target.assign(&(&kp_host + &t));
  20 | |         }
     | |_________^ `NonNull<A>` cannot be shared between threads safely
     |
     = help: within `{closure@src/patch_tracker/test.rs:16:9: 16:33}`, the trait `Sync` is not implemented for `NonNull<A>`

Is this an expected behavior ?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions