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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions