Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add accumulate_axis_inplace method and implement NdProducer for RawArrayView/Mut #611

Merged
merged 4 commits into from Sep 18, 2019

Conversation

jturner314
Copy link
Member

@jturner314 jturner314 commented Mar 27, 2019

This accumulate_axis_inplace method is a non-cloning version of the accumulate_axis_method proposed in #513.

@bluss
Copy link
Member

bluss commented Sep 8, 2019

Amazing, we'll need this to improve upon .. so many things, including how we handle uninitalized values. I'll need to remind myself to come back to this.

@bluss bluss self-requested a review September 8, 2019 22:28
prev.slice_axis_inplace(axis, Slice::from(..-1));
let mut curr = self.raw_view_mut();
curr.slice_axis_inplace(axis, Slice::from(1..));
// This implementation relies on `Zip` iterating along `axis` in order.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I guess we'll think about if that's something we can guarantee. Probably not publically.

@bluss
Copy link
Member

bluss commented Sep 11, 2019

Rebased to resolve the conflict. I had to reformat and fix some things for NonNull. I added a commit on top with what I think would be the careful way to use raw view (see commit log). I haven't studied the unsafe coding guidelines that well, so this is just my rough understanding.

@bluss
Copy link
Member

bluss commented Sep 11, 2019

Updating because RawView + Zip should be an awesome ally in solving fundamentals, like how to do more operations in place or without excessive copying, or just to handle uninitialized data better.

@bluss
Copy link
Member

bluss commented Sep 11, 2019

The format checker wants to ruin the formatting of the arrays in tests, and I'd like to make it less strict :/

We had:

1. let ptr1 = self.raw_view(); // Borrow &self
2. let ptr2 = self.raw_view_mut(); // Borrow &mut self
3. Use ptr1 and ptr2

While I'm not an expert at the unsafe coding guidelines for Rust, and
there are more places in ndarray to revisit, I think it's best to change
change 1 and 2 - they don't pass my internalized borrow checker.

It seems as though the steps 1, 2, 3 could be against the rules as ptr1
is borrowed from the array data, and its scope straddles the mut borrow
of the array data in 2.

For this reason, I think this would be better:

1. let ptr2 = self.raw_view_mut() // Borrow &mut self
2. let ptr1 = derive from ptr2
3. use ptr1 and ptr2

RawView should hopefully be our ally in making a better ndarray from the
foundation.
/// ],
/// );
/// ```
pub fn accumulate_axis_inplace<F>(&mut self, axis: Axis, mut f: F)
Copy link
Member

@bluss bluss Sep 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is a neat demonstration of an array Zip-ing with itself. It seems a bit niche but we can of course include it. But the question of course goes out, how do we generalize this. Apart from the raw pointer Zip, of course? How to generalize the Self-zip in a safe Rust package?

Apart from returning to the idea of an array view of Cells, which is not hard to do.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we really need to wait until Rust has generic associated types before we can write good self-Zip abstractions. We can do things like this today:

    /// Folds over the mutable windows of the specified size.
    pub fn windows_mut_fold<E, B, F>(&mut self, window_size: E, init: B, f: F)
    where
        E: IntoDimension<Dim = D>,
        F: for<'a> FnMut(B, ArrayViewMut<'a, A, D>) -> B,
        S: DataMut,
    {
        // ...
    }

but without generic associated types, we can't abstract this into a WindowsMut producer that implements a trait, because the item type (which is an associated type of the trait) has a temporary lifetime.

prev.slice_axis_inplace(axis, Slice::from(..-1));
curr.slice_axis_inplace(axis, Slice::from(1..));
// This implementation relies on `Zip` iterating along `axis` in order.
Zip::from(prev).and(curr).apply(|prev, curr| unsafe {
Copy link
Member

@bluss bluss Sep 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a particularly simple Zip - the prev and curr pointer are always just the stride of axis apart, and in that sense it could have been just a unary loop, with one pointer prev and another prev + offset. If the Zip only compiles to the equivalent, all the better, then we have a nice way to express exactly that. (But I guess Zip has some kind of overhead here.)

@bluss
Copy link
Member

bluss commented Sep 18, 2019

Thanks for this, the ndproducer impls will be very useful going forward. And I guess we should have discussions about how to use it correctly (and eventually produce docs for that when we know 🙂 )

@bluss bluss merged commit 642a44c into rust-ndarray:master Sep 18, 2019
@jturner314 jturner314 deleted the accumulate-axis-inplace branch September 18, 2019 19:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants