-
Notifications
You must be signed in to change notification settings - Fork 308
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
Improved arithmetic operations for arrays #699
Comments
About compile time Remember: When working on the crate, compile time of the There are some strategies to keep in mind for codegen compilation time:
But then there's the question of "Rust" focused compilation time:
Looking at ndarray's -Ztime-passes without incremental compilation, the following items use the most time:
So it is indeed a mostly "Rust" bound compilation with little time in code generation. And we have a possibility that the Rust bound compilation passes will be proportional to the amount of new methods we define. I'd wager it would be good with fewer, more generic trait impls for this reason? (And then apply tips 1 and 2 to decrease compile time in the end user application.) |
I agree on the goals and the outlined pain points/strategy. A couple of points I'd like to add to the discussion:
|
#478 is related because it contains the idea of treating an array of While this is a load of factors to consider, we should not fix this in one pull request! We should understand the landscape, talk about plans and make gradual fixes. |
In #744, I've proposed relaxing all |
One other comment on this issue -- we can implement co-broadcasting for arbitrary dimension types, not just pub trait PartialOrdDim<Rhs: Dimension>: Dimension {
type Max: Dimension;
type Min: Dimension;
// possibly other useful stuff
}
impl<D: Dimension> PartialOrdDim<Ix3> for Ix2 {
type Max = Ix3;
type Min = Ix2;
}
impl<D: Dimension> PartialOrdDim<IxDyn> for Ix2 {
type Max = IxDyn;
type Min = IxDyn;
}
// ...
impl<'a, A, B, S, S2, D, E> $trt<&'a ArrayBase<S2, E>> for &'a ArrayBase<S, D>
where
A: Clone + $trt<B>,
B: Clone,
S: Data<Elem=A>,
S2: Data<Elem=B>,
D: Dimension + PartialOrdDim<E>,
E: Dimension,
{
type Output = Array<<A as $trt<B>>::Output, <D as PartialOrdDim<E>>::Max>;
fn $mth(self, rhs: &'a ArrayBase<S2, E>) -> Self::Output {
// ...
}
} |
FWIW, I'm just getting started with ndarray and basically didn't figure out how to do error[E0271]: type mismatch resolving `<ViewRepr<&mut f32> as RawData>::Elem == ArrayBase<ViewRepr<&f32>, Dim<[usize; 1]>>`
--> tools/src/bin/build-index.rs:58:26
|
58 | sentence += ArrayView1::from(&state.buf);
| ^^ expected `f32`, found struct `ArrayBase`
|
= note: expected type `f32`
found struct `ArrayBase<ViewRepr<&f32>, Dim<[usize; 1]>>`
= note: required because of the requirements on the impl of `AddAssign<ArrayBase<ViewRepr<&f32>, Dim<[usize; 1]>>>` for `ArrayBase<ViewRepr<&mut f32>, Dim<[usize; 1]>>`
error[E0277]: the trait bound `ArrayBase<ViewRepr<&f32>, Dim<[usize; 1]>>: ScalarOperand` is not satisfied
--> tools/src/bin/build-index.rs:58:26
|
58 | sentence += ArrayView1::from(&state.buf);
| ^^ the trait `ScalarOperand` is not implemented for `ArrayBase<ViewRepr<&f32>, Dim<[usize; 1]>>`
|
= note: required because of the requirements on the impl of `AddAssign<ArrayBase<ViewRepr<&f32>, Dim<[usize; 1]>>>` for `ArrayBase<ViewRepr<&mut f32>, Dim<[usize; 1]>>`
error[E0271]: type mismatch resolving `<ViewRepr<&f32> as RawData>::Elem == ArrayBase<ViewRepr<&f32>, Dim<[usize; 1]>>`
--> tools/src/bin/build-index.rs:58:26
|
58 | sentence += ArrayView1::from(&state.buf);
| ^^ expected `f32`, found struct `ArrayBase`
|
= note: expected type `f32`
found struct `ArrayBase<ViewRepr<&f32>, Dim<[usize; 1]>>`
= note: required because of the requirements on the impl of `AddAssign` for `ArrayBase<ViewRepr<&f32>, Dim<[usize; 1]>>`
= note: required because of the requirements on the impl of `AddAssign<ArrayBase<ViewRepr<&f32>, Dim<[usize; 1]>>>` for `ArrayBase<ViewRepr<&mut f32>, Dim<[usize; 1]>>`
error[E0277]: the trait bound `ViewRepr<&f32>: DataMut` is not satisfied
--> tools/src/bin/build-index.rs:58:26
|
58 | sentence += ArrayView1::from(&state.buf);
| ^^ the trait `DataMut` is not implemented for `ViewRepr<&f32>`
|
= help: the following implementations were found:
<ViewRepr<&'a mut A> as DataMut>
= note: required because of the requirements on the impl of `AddAssign` for `ArrayBase<ViewRepr<&f32>, Dim<[usize; 1]>>`
= note: required because of the requirements on the impl of `AddAssign<ArrayBase<ViewRepr<&f32>, Dim<[usize; 1]>>>` for `ArrayBase<ViewRepr<&mut f32>, Dim<[usize; 1]>>` Not sure if that's related to this issue, but I looked for examples doing this kind of thing and a bunch of the documentation on |
@djc You might need to make a reference to sentence += &ArrayView1::from(&state.buf) |
The docs cover this in the designated section, with examples https://docs.rs/ndarray/0.14.0/ndarray/struct.ArrayBase.html#arithmetic-operations |
(This is a collaborative issue, please edit and add points, if applicable, or join the discussion in the issue below)
For context, please read the ArrayBase documentation on Arithmetic Operations first.
Goals
A. Allocate only what's needed and reuse when possible
B. Copy only what's needed, compute and insert in place otherwise
C. Autovectorization and vectorization — single threaded performance of the computation
Non-Goals
Parallelization and multithreading is not in scope for this issue
Prioritization
Known Problems in Current Implementation
self.to_owned().add(rhs)
to implement it, while it could be implemented without copying the first operand's dataelt1.clone() + elt2.clone()
in some places.Expanding the Number of Implementations
Zip
allows the user many ways to write in place operations themselves, and in this case, there'sgeneral_mat_mut
which can perform the operation A += X × Y in place.Which solution is better for compile time?
A. Make impl blocks more generic (admitting more array kinds per impl, for example admitting both &A and &mut A)
B. Expand the number of impls to cover all cases (for example, one for each combination of &A/&mut A)
Consider both plain ndarray "cargo build" compile time, and compile time when ndarray is used in a project and compiles to non-generic code.
Co-broadcasting for Dynamic dimensionality
For static dimensionality array operations we use right hand side broadcasting: in A @ B, we can attempt to broadcast B to the shape of A.
For dynamic dimensionality operations, we can improve this to co-broadcasting so that A @ B can result in an array with a shape that's neither that of A or B.
Note: Co-broadcasting only ever expands the number of arrays that are compatible in operations, it does not change the result of operations that are already permitted by the right hand side broadcasting rule.
Related issues:
The text was updated successfully, but these errors were encountered: