-
Notifications
You must be signed in to change notification settings - Fork 84
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 SimdArray trait and safe gather/scatter API #139
Conversation
db35b39
to
2e13093
Compare
Naming question: Do we want the Maybe like: // excuse my syntax
impl ... for SimdUsize<...> {
fn gather_or<T>(self, slice: &[T], mask: ..., fallback: Simd<[T; LANES]>) -> Simd<[T; LANES]>;
fn gather_or_default<T>(self, slice: &[T], mask: ...) -> ...;
} |
discussed in meeting, consensus was largely... On the trait
On the methods
|
This provides a general framework for describing relationships between vector types and scalar types.
2e13093
to
0b6cea3
Compare
0b6cea3
to
81ceda8
Compare
/// A representation of a vector as an "array" with indices, implementing | ||
/// operations applicable to any vector type based solely on "having lanes", | ||
/// and describing relationships between vector and scalar types. | ||
pub trait SimdArray<const LANES: usize>: crate::LanesAtMost32 |
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.
Looking this over again, shouldn't the lane count be an associated const?
pub trait SimdArray {
const LANES: usize;
}
It's impossible to implement SimdArray
with different lengths for a single type.
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.
Hm... is that a bug?
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 am OK with using an assoc const fwiw, I just genuinely don't know which one would actually be best here. My operating assumption is that they have different implications re: const unification and type inference and I don't know what actually will offer the more ergonomic API until we rework more stuff.
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.
The associated const would let you do something like <T as SimdArray>::LANES
which I could see being useful. No easy way to extract the lane count otherwise, I think.
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.
Also it follows the best practice of "if you want to allow this type to implement the trait multiple times, use a type const parameter, otherwise use an associated type const".
EDIT: lol i said it backwards first.
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 add the assoc const on its own but removing the const from the trait definition induces a cycle in evaluating the well-formedness of the const generic, so I think it can't be done.
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'll check it out in a bit, just to see if I can convince it. I don't see why it shouldn't work.
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.
cc @rust-lang/project-const-generics since we seem to be running into an amusing niche case in our expectations of how const things work and interact with Rust programming idioms, vs. how they do in practice.
for note: my attempt was to bound everything currently described by LANES on Self::LANES
and instead write stuff like
impl SimdArray for Simd{Ty}<LANES> {
const LANES: usize = LANES;
}
and I experimented with a few different configurations of where-bounds and the like, but I kept hitting cycles or outright failures to type check.
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.
After finding that the problem is probably in the bounds not being moved mostly into the implementations of the traits, we will probably catch up to refactoring this in after a bit more tinkering around.
ad8171e
to
f38659a
Compare
Combine LanesAtMost32 and SimdArray into a single trait "Vector" Attempts to fix some unresolved questions in #139 regarding `SimdArray` having a generic parameter. In particular, this made it not appropriate for replacing `LanesAtMost32`. Additionally, it made it impossible to use in a context where you otherwise don't know the lane count, e.g. `impl Vector`. An unfortunate side effect of this change is that scatter/gather no longer work in the trait (nor does anything else that references the lane count in a type. This requires the super-unstable `const_evaluatable_checked` feature). I also threw in the change from `as_slice` to `as_array` as discussed in zulip, and fixes #51.
This PR has four parts, without which it doesn't make a lot of sense:
SimdArray
trait for abstraction over vectors.SimdArray::gather_{or, or_default, select}
.SimdArray::scatter{,_select}
.