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

Simd<&T, N> #200

Open
programmerjake opened this issue Nov 24, 2021 · 12 comments
Open

Simd<&T, N> #200

programmerjake opened this issue Nov 24, 2021 · 12 comments
Labels
C-feature-request Category: a feature request, i.e. not implemented / a PR

Comments

@programmerjake
Copy link
Member

I didn't see an issue tracking vectors of pointers/references, so I'm opening one. Feel free to edit as necessary.

@programmerjake programmerjake added the C-feature-request Category: a feature request, i.e. not implemented / a PR label Nov 24, 2021
@programmerjake
Copy link
Member Author

One thing that just occurred to me in relation to #195, #198, and #199:
We can't depend on user-implementable traits such as Add or PartialOrd when we eventually get Simd<&T, N> cuz references are #[fundamental] so users can implement &T: Add which would allow unsafely calling simd_reduce_add with argument type &T.

@workingjubilee
Copy link
Member

workingjubilee commented Nov 24, 2021

...if we get Simd<&T, N>. That is the best argument I have heard for not allowing so.
But also we currently don't have such a generic impl that would permit such for simd_reduce_add. Perhaps you meant simd_reduce_and.

@calebzulawski
Copy link
Member

Or, we should not use the ops traits on the scalar type and instead use our own sealed traits that explicitly indicate which functions can monomorphize (as I have said repeatedly), and then we can allow vectors of references just fine. The ops traits do not actually mean anything whatsoever regarding intrinsics and this is an example of why using them for this is a hack that only works with number types. I think vectors of references would be useful for gather and maybe a few other things and this isn't a good reason to rule them out.

@workingjubilee
Copy link
Member

We can only use thin pointers anyway, though. If it's a fat borrow, and any instance of &T can be, it suddenly won't fit inside the same vector lanes as a thin &T and breaks all the invariants we have about scalars, including the internal logic gather_select_unchecked relies on.

@programmerjake
Copy link
Member Author

vectors of fat pointers should totally be doable by just allocating i128 lanes or twice as many lanes or similar (maybe both at different times?), though, yeah, we'll probably at first want a T: Thin + ?Sized bound for Simd<&'a T, N>. Vectors of fat pointers will also need to deal with the possible future extensions of fat pointers to more arbitrary metadata types for &dyn Debug + Display or custom metadata.

@Lokathor
Copy link
Contributor

what would a vector of fat pointers even do. Like are we trying to imagine that at some point you could vectorize all of rust, or what.

@programmerjake
Copy link
Member Author

One example where vectors of references would be nice:

pub struct TreeNode<'a> {
    data: Cell<isize>,
    left: &'a TreeNode<'a>,
    right: &'a TreeNode<'a>,
}

pub fn simd_binary_search<'a>(mut node: Simd<&'a TreeNode<'a>, 4>, empty_node: &'a TreeNode<'a>, key: Simd<isize, 4>) -> Mask<isize, 4> {
    let mut done = Mask::from(false);
    let mut found = Mask::from(false);
    while !done.all() {
        let data: Simd<i32, 4> = node.field_ref(field!(TreeNode::data)).gather_cells();
        let gt = data.lane_gt(key);
        found = data.lane_eq(key);
        done = found | node.lane_ptr_eq(Simd::splat(empty_node));
        let child = gt.select(node.field_ref(field!(TreeNode::left)), node.field_ref(field!(TreeNode::right)));
        node = done.select(node, child);
    }
    found
}

@programmerjake
Copy link
Member Author

what would a vector of fat pointers even do. Like are we trying to imagine that at some point you could vectorize all of rust, or what.

well, I would like to be able to vectorize a decent subset of rust...idk that fat pointers needs to be in that subset, but I definitely think thin pointers/references should!

@workingjubilee
Copy link
Member

Fat pointers shouldn't really be handled via Simd<i128, N>, they should have a layout more like

struct FatPtr<T, const N> {
   ptr: Simd<*const T, N>
   len: Simd<usize, N>
}

for all the usual reasons to use SoA constructions.

@programmerjake
Copy link
Member Author

Fat pointers shouldn't really be handled via Simd<i128, N>, they should have a layout more like

struct FatPtr<T, const N> {
   ptr: Simd<*const T, N>
   len: Simd<usize, N>
}

for all the usual reasons to use SoA constructions.

that breaks assumptions that Simd<T, N> is laid out like [T; N] in memory.

@workingjubilee
Copy link
Member

Only if it is offered as the same type, which it should probably not be.

@Lokathor
Copy link
Contributor

Lokathor commented Dec 3, 2021

Yeah i mean hardware doesn't have anything at all like a rust fat pointer as far as i know, so we don't need to represent our "simd version of fat pointers" like anything in particular because we're fudging it no matter what.

@calebzulawski calebzulawski changed the title vectors of pointers Simd<&T, N> Jul 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-feature-request Category: a feature request, i.e. not implemented / a PR
Projects
None yet
Development

No branches or pull requests

4 participants