-
Notifications
You must be signed in to change notification settings - Fork 307
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
Added stride support to Windows
#1249
Added stride support to Windows
#1249
Conversation
e9deaf3
to
2c0ae32
Compare
Now that you created |
Great insight, changes have been applied, if there is a more effective way of creating a unit stride please let me know. |
@nilgoyette Please let me know if you would like me to change the |
Yes, their description will be identical except for one detail. Good idea. |
Any more feedback would be highly appreciated! If collaborators would want me to squash all commits into one then would be happy to do so. |
Thank you for your contribution @LazaroHurtado |
let window_strides = a.strides.clone(); | ||
|
||
let mut array_strides = a.strides.clone(); | ||
for (arr_stride, ix_stride) in array_strides.slice_mut().iter_mut().zip(strides_d.slice()) { | ||
*arr_stride *= ix_stride; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some inputs this multiplication will wrap around. Check on input is needed so that the resulting array view is always valid in those and other cases, otherwise it's a "back door" into creating an invalid array view and UB.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! I can release a follow-up PR using checked_mul
and assert_ne!
on the checked result with None
ensuring the array view is valid, would you consider this sufficient?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can write a longer comment, let's see what more there is. It is not exactly the solution.
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
This comment was marked as duplicate.
This comment was marked as duplicate.
Sorry, something went wrong.
@nilgoyette first of all I'm apologizing to you. I want to contribute net positive here (and not net negative) and chiming in like I did with stuff to second-guess anyone's review is not what I want to do. I want ndarray to live without me, and then it needs to merge stuff without my view of things have to be (which I repeat because that's what I've long accepted, but it's harder to do than say). 🙂 I see you're doing reviews and getting stuff merged and that's great 🙂. Be direct in what you need from me, because I might not be around to do it otherwise. |
let window_strides = a.strides.clone(); | ||
|
||
let mut array_strides = a.strides.clone(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe a better name is base_strides
let window_strides = a.strides.clone(); | ||
|
||
let mut array_strides = a.strides.clone(); | ||
for (arr_stride, ix_stride) in array_strides.slice_mut().iter_mut().zip(strides_d.slice()) { | ||
*arr_stride *= ix_stride; |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
assert_ne!(ws, 0, "window-size must not be zero!"); | ||
assert_ne!(stride, 0, "stride cannot have a dimension as zero!"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not a dimension but the stride value
for (arr_stride, ix_stride) in array_strides.slice_mut().iter_mut().zip(strides_d.slice()) { | ||
*arr_stride *= ix_stride; | ||
} | ||
|
||
unsafe { | ||
Windows { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll put in some comments here (this is my mental process now that I come back to this, I've implemented this, but maybe needed some comments.)
// base outlines the traversal: each element in base <=> each produced window's first element
// window and window strides determines size and strides of the array views produced
let window_strides = a.strides.clone(); | ||
|
||
let mut array_strides = a.strides.clone(); | ||
for (arr_stride, ix_stride) in array_strides.slice_mut().iter_mut().zip(strides_d.slice()) { | ||
*arr_stride *= ix_stride; |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
let window_strides = a.strides.clone(); | ||
|
||
let mut array_strides = a.strides.clone(); | ||
for (arr_stride, ix_stride) in array_strides.slice_mut().iter_mut().zip(strides_d.slice()) { | ||
*arr_stride *= ix_stride; |
This comment was marked as duplicate.
This comment was marked as duplicate.
Sorry, something went wrong.
@LazaroHurtado I've rewritten my comment to be shorter and more clear (and hidden the old ones)
We want to compute let window_strides = a.strides.clone();
let mut base = a;
base.slice_each_axis_inplace(|ax_desc| {
let len = ax_desc.len;
let wsz = window[ax_desc.axis.index()];
if len < wsz {
Slice::new(0, Some(0), 1)
} else {
Slice::new(0, Some((len - wsz + 1) as isize), 1)
}
});
Windows {
base,
window,
strides: window_strides,
} |
Thank you @bluss for providing your feedback on this new feature, I highly appreciate it. I will take responsibility for making the proper changes to close out any potential bugs or improve code readability related to my work. Please be patient with me since I am still not 100% familiar with this crate and I have limited free time, nonetheless, I will deliver and keep you and @nilgoyette in the loop. |
Thank you @bluss for "refactoring" your comments. I don't know about@LazaroHurtado , but I was somewhat confused :| As for the personnal comment
|
Currently the
ArrayBase::windows()
method creates an iterator of windows with a stride of 1 along all axes of the given array's dimensions. This is limiting the functionality of windows on arrays. One use case where having the ability to specify the stride is necessary is in convolutional neural networks, where what ndarray calls a window is basically a kernel.Important notes
ArrayView
found in thebase
field of theWindows
struct. This change is derived from this formula.The ordering for the stride isThis was the original intention but noticing that the formula also follows outermost axis first, similar to indexing an ndarray, I believe it should be similar.(inner_most_axis, ..., outer_most_axis)
. This is because the axis that the windows gets pushed along first is the inner most axis...